【题解】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;
} 
posted @ 2019-04-19 21:47  章鱼那个哥  阅读(172)  评论(0编辑  收藏  举报