[bzoj2621] [USACO12MAR]摩天大楼里的奶牛Cows in a Skyscraper

题目链接

状压\(dp\)

根据套路,先设\(f[sta]\)为状态为\(sta\)时所用的最小分组数。

可以发现,这个状态不好转移,无法判断是否可以装下新的一个物品。于是再设一个状态\(g[sta]\)表示状态为\(sta\)时 每组剩下的体积的最大值 的最大值,当枚举状态为\(sta\),枚举到第\(i\)个时,可以得到\(g\)的转移:

\[g[v]=max(g[v],g[sta]-w[i]) \]

其中,\(v​\)为转移后的状态。

然后每次就可以根据\(g\)来转移\(f\)了。

#pragma GCC optimize(3)
#include<bits/stdc++.h>
using namespace std;
void read(int &x){
    x=0;int f=1;char ch=getchar();
    for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-f;
    for(;isdigit(ch);ch=getchar()) x=(x<<1)+(x<<3)+ch-'0';x*=f;
}
#define write(x) printf("%d\n",x)
int f[(1<<18)+10],g[(1<<18)+10],n,w[20],W;
int main(){
    read(n),read(W);for(int i=1;i<=n;i++) read(w[i]);
    memset(f,63,sizeof f);f[0]=1,g[0]=W;
    for(int i=0;i<(1<<n);i++)
        for(int j=1,v=i|(1<<(j-1));j<=n;j++,v=i|(1<<(j-1)))
            if(!(i&(1<<(j-1)))) 
                if(g[i]>=w[j]&&f[i]<=f[v]) f[v]=f[i],g[v]=max(g[v],g[i]-w[j]);
                else if(g[i]<w[j]&&f[i]+1<=f[v]) f[v]=f[i]+1,g[v]=max(g[v],W-w[j]);
    write(f[(1<<n)-1]);
    return 0;
}

posted @ 2018-10-22 20:44  Hyscere  阅读(127)  评论(0编辑  收藏  举报