POJ1742 Coins
多重背包问题,bool型染色背包。
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
int a[150],c[150];
int sum[100005];
bool f[100005];
int main(){
int n,m;
while (scanf("%d%d",&n,&m),n!=0&&m!=0){
for (int i=1;i<=n;i++) scanf("%d",&a[i]);
for (int i=1;i<=n;i++) scanf("%d",&c[i]);
memset(f,false,sizeof(f));
f[0]=true;
int ans=0;
for (int i=1;i<=n;i++){
memset(sum,0,sizeof(sum));
int v=a[i];
for (int j=v;j<=m;j++){
if (!f[j]&&f[j-v]&&sum[j-v]<c[i]){
f[j]=true;
sum[j]=sum[j-v]+1;
ans++;
}
}
}
printf("%d\n",ans);
}
return 0;
}
POJ1014 Dividing
重量为1,2,3,4,5,6 的石子 的数量依次告诉你,问是否可以分成平均的两堆。
分析:先判断sum的奇偶,若为偶数,便是容量为sum/2的多重背包,可以采用bool染色的写法。
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
int a[10];
int dp[420050],cnt[420050];
int main(){
int n=6,cases=0;
for (int i=1;i<=n;i++) scanf("%d",&a[i]);
bool flag=true;
while (flag){
printf("Collection #%d:\n",++cases);
int sum=0;
for (int i=1;i<=n;i++){
sum+=a[i]*i;
}
if (sum%2==0){
memset(dp,false,sizeof(dp));
dp[0]=true;
for (int i=1;i<=n;i++){
memset(cnt,0,sizeof(cnt));
for (int j=i;j<=sum/2;j++){
if (dp[j-i]&&!dp[j]&&cnt[j-i]<a[i]){
dp[j]=true;
cnt[j]=cnt[j-i]+1;
}
}
}
if (dp[sum/2]) printf("Can be divided.\n\n");
else printf("Can't be divided.\n\n");
}
else printf("Can't be divided.\n\n");
flag=false;
for (int i=1;i<=n;i++){
scanf("%d",&a[i]);
if (a[i]!=0) flag=true;
}
}
}
ZOJ3623 Battle Ships
非常有意思的完全背包问题,值得思考、
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
int dp[361];
int main(){
int n,m,t,l;
while (~scanf("%d%d",&n,&m)){
memset(dp,0,sizeof(dp));
dp[0]=0;
for (int i=1;i<=n;i++){
scanf("%d%d",&t,&l);
for (int j=t;j<=360;j++){
dp[j]=max(dp[j],dp[j-t]+(j-t)*l);
}
}
for (int i=1;i<=360;i++){
if (dp[i]>=m){
printf("%d\n",i);
break;
}
}
}
return 0;
}
更多背包问题,等待更新。