CFGym 101002C 状压DP

来源:互联网 发布:淘宝led散热片 编辑:程序博客网 时间:2024/06/16 14:43

题意

N种卡片,用K种格子去装。问浪费的空间。

题解

比赛的时候一直想的是斜率优化,然后成功TLE。看了别的队的代码才意识到是一个状压DP。
至于DP的方法,采用最暴力的方法就可以了。我们首先可以算出来任意一种长和宽的组合能包含哪几种卡片。然后可以暴力算出来任意一种长和宽的组合选择任意的卡片所需要的花费。最后DP,状态放在最外层,代表当前选择的卡片,格子数放在第二层,DP数组记录这两个状态就足够了。暴力对任意一种长和宽的组合所能包含的卡片进行状态转移。最后选择用0-K种盒子且包含所有状态,浪费最小的值就可以了。

注意事项

在进行状态转移的时候有一点小技巧,如果没注意到的话,会一直无法过样例。

int ss=c[j][p]|s;dp[ss][i+1]=min(dp[ss][i+1],dp[s][i]+cost[ss^s][j][p]);

注意这里很有趣的一个去重小技巧。因为有可能当前的状态已经包含了新增状态的一部分。所以需要去重,已经有的状态不需要重复花费。

代码

#include <iostream>#include<cstdio>#include<algorithm>#include<cstring>#include<vector>#include<cmath>#include<queue>#include<string>#include<set>#include<map>#include<bitset>#include<stack>#include<string>#define UP(i,l,h) for(int i=l;i<h;i++)#define DOWN(i,h,l) for(int i=h-1;i>=l;i--)#define W(a) while(a)#define MEM(a,b) memset(a,b,sizeof(a))#define LL long long#define INF 0x3f3f3f3f3f3f3f3f#define MAXN 17#define MOD 1000000007#define EPS 1e-3#define int LLusing namespace std;int h[MAXN],w[MAXN],a[MAXN],x[MAXN],y[MAXN],dp[1<<MAXN][MAXN],cost[1<<MAXN][MAXN][MAXN],c[MAXN][MAXN];main() {    int n,k;    scanf("%I64d%I64d",&n,&k);    UP(i,0,n) {        scanf("%I64d%I64d%I64d",&h[i],&w[i],&a[i]);        x[i]=h[i];        y[i]=w[i];    }    sort(x,x+n);    sort(y,y+n);    UP(i,0,n) {        UP(j,0,n) {            UP(p,0,n) {                if(h[p]<=x[i]&&w[p]<=y[j]) c[i][j]|=(1<<p);            }        }    }    UP(i,0,n) {        UP(j,0,n) {            UP(s,0,1<<n) {                UP(p,0,n) {                    if(s&(1<<p)) cost[s][i][j]+=a[p]*(x[i]*y[j]-h[p]*w[p]);                }            }        }    }    MEM(dp,INF);    dp[0][0]=0;    UP(s,0,1<<n) {        UP(i,0,k) {            if(dp[s][i]==INF) continue;            UP(j,0,n) {                UP(p,0,n) {                    int ss=c[j][p]|s;                    dp[ss][i+1]=min(dp[ss][i+1],dp[s][i]+cost[ss^s][j][p]);//                    cout<<dp[s|c[j][p]][i+1]<<" "<<(s|c[j][p])<<endl;                }            }        }    }    int ans=INF;    UP(i,0,k+1) ans=min(ans,dp[(1<<n)-1][i]);    printf("%I64d\n",ans);}
原创粉丝点击