【题解】P3052 [USACO12MAR]摩天大楼里的奶牛Cows in a Skyscraper
\(Description:\)
给出n个物品,体积为w[i],现把其分成若干组,要求每组总体积<=W,问最小分组。
\(Sample\) \(Input:\)
4 10
5
6
3
7 3
\(Sample\) \(Output:\)
3
\(Hint:\)
\(n<=18\)
\(Solution:\)
喵的,如果这题数据范围再小一点,我就水过去了。。。
暴力上来就写了PRZ的做法,拿到了 \(8\) 分的好成绩。
正解:
记录两个数组:
最优方案 \(f[]\)
最多最后一次电梯的最大剩余
转移时两个都更新一下就好了。
#include<bits/stdc++.h>
using namespace std;
int n,m,Max_status;
const int N=20,M=(1<<18)+5;
int w[N],res[M],f[M];
// res => 最优方案下留下的最多体积
// f => 最有方案要的电梯乘坐次数
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;++i) scanf("%d",&w[i]);
Max_status=(1<<n)-1;
memset(f,0x3f,sizeof(f));
f[0]=1; res[0]=m;// 一开始已经要做一次电梯
for(int s=0;s<=Max_status;++s){
for(int i=1;i<=n;++i) if(!(s&(1<<(i-1)))){
// 这次塞下了
if(res[s]>=w[i] && f[s|(1<<(i-1))]>=f[s])
f[s|(1<<(i-1))]=min(f[s|(1<<(i-1))],f[s]),
res[s|(1<<(i-1))]=max(res[s|(1<<(i-1))],res[s]-w[i]);
// 这次放不下
else if(res[s]<w[i] && f[s|(1<<(i-1))]>=f[s]+1)
f[s|(1<<(i-1))]=min(f[s|(1<<(i-1))],f[s]+1),
res[s|(1<<(i-1))]=max(res[s|(1<<(i-1))],m-w[i]);
}
}
printf("%d\n",f[Max_status]);
return 0;
}