[PA2014]Pakowanie

[PA2014]Pakowanie

题目大意:

(n(nle24))个物品和(m(mle100))个背包,每个物体有一个体积(a_i),每个背包有一个容量(c_i)。问装完所有物品至少需要几个包?

思路:

一个贪心的策略是优先装大的包,显然这样可以最少化所用背包的数量。

将所有的背包按照容量从大到小排序,(f[s])表示装了物品的状态为(s),用了前(f[s])大的背包。(g[s])表示装了物品的状态为(s),最后那个背包用了(g[s])的容量。

随便转移就好了。

时间复杂度(mathcal O(2^nn))

源代码:

#include<cstdio>
#include<cctype>
#include<climits>
#include<algorithm>
#include<functional>
inline int getint() {
	register char ch;
	while(!isdigit(ch=getchar()));
	register int x=ch^'0';
	while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
	return x;
}
const int N=24,M=101;
int a[N],c[M],f[1<<N],g[1<<N];
int main() {
	const int n=getint(),m=getint();
	for(register int i=0;i<n;i++) a[i]=getint();
	for(register int i=1;i<=m;i++) c[i]=getint();
	std::sort(&c[1],&c[m]+1,std::greater<int>());
	std::fill(&f[1],&f[1<<n],INT_MAX);
	for(register int i=1;i<1<<n;i++) {
		for(register int j=0;j<n;j++) {
			if(!((i>>j)&1)) continue;
			const int k=i^(1<<j);
			const int tmp1=g[k]+a[j]<=c[f[k]]?f[k]:f[k]+1;
			const int tmp2=tmp1==f[k]?g[k]+a[j]:a[j];
			if(tmp2>c[tmp1]) continue;
			if(tmp1<f[i]) {
				f[i]=tmp1;
				g[i]=INT_MAX;
			}
			if(tmp1==f[i]) g[i]=std::min(g[i],tmp2);
		}
	}
	if(f[(1<<n)-1]==INT_MAX) {
		puts("NIE");
		return 0;
	}
	printf("%d
",f[(1<<n)-1]);
	return 0;
}
原文地址:https://www.cnblogs.com/skylee03/p/9470680.html