1.解法一:完全背包
#include<iostream> #include<cstdio> using namespace std; #define MAX(a,b) (a>b)?a:b const int SIZE=500000+16; int dp[SIZE]; int bag[7]; int nLimit; void ZeroOnePack(int cost, int value) { for(int i=nLimit; i>=cost; i--) dp[i]=MAX(dp[i],dp[i-cost]+value); } void CompletePack(int cost, int value) { for(int i=cost; i<=nLimit; i++) dp[i]=MAX(dp[i],dp[i-cost]+value); } void MultiplyPack(int cost, int value, int amount) { if(amount*cost>=nLimit) CompletePack(cost,value); else { int k=1; while(k<amount) { ZeroOnePack(k*cost, k*value); amount-=k; k<<=1; } ZeroOnePack(amount*cost,amount*value); } } bool CheckFinish() { for(int i=1;i<=6;i++) if(bag[i]!=0) return false; return true; } int main() { int T=0; while(true) { int sum=0; for(int i=1; i<=6; i++) { scanf("%d",&bag[i]); sum+=bag[i]*i; } if(CheckFinish()) break; printf("Collection #%d:\n",++T); if(sum%2==1) { printf("Can‘t be divided.\n"); } else { memset(dp,0,sizeof(dp)); nLimit=sum/2; for(int i=1;i<=6;i++) { MultiplyPack(i,i,bag[i]); } if(dp[nLimit]==nLimit) printf("Can be divided.\n"); else printf("Can‘t be divided.\n"); } printf("\n"); } return 0; }
2.解法二:多重部分和
#include<cstdio> #include<cstring> using namespace std; const int SIZE=120000+16; int a[6]; int dp[SIZE]; bool check() { for(int i=0;i<6;i++) if(a[i]!=0) return true; return false; } int sum; int main() { int t=0; while(true) { sum=0; for(int i=0;i<6;i++) { scanf("%d",&a[i]); sum+=(i+1)*a[i]; } if(!check()) break; printf("Collection #%d:\n",++t); if(sum%2==1) { printf("Can‘t be divided.\n"); } else { memset(dp,-1,sizeof(dp)); int k=sum/2; dp[0]=0; for(int i=0;i<6;i++) { for(int j=0;j<=k;j++) { if(dp[j]>=0) { dp[j]=a[i]; } else if(j<(i+1)||dp[j-(i+1)]<=0) { dp[j]=-1; } else { dp[j]=dp[j-(i+1)]-1; } } } if(dp[k]>=0) { printf("Can be divided.\n"); } else { printf("Can‘t be divided.\n"); } } printf("\n"); } return 0; }
3.解法三:判断完全背包可否装满
#include<iostream> #include<cstdio> using namespace std; #define MAX(a,b) (a>b)?a:b const int SIZE=500000+16; const int INF=100000; int dp[SIZE]; int bag[7]; int nLimit; bool CheckFinish() { for(int i=1;i<=6;i++) if(bag[i]!=0) return false; return true; } int main() { int T=0; while(true) { int sum=0; for(int i=1; i<=6; i++) { scanf("%d",&bag[i]); sum+=bag[i]*i; } if(CheckFinish()) break; printf("Collection #%d:\n",++T); if(sum%2==1) { printf("Can‘t be divided.\n"); } else { nLimit=sum/2; memset(dp,0,sizeof(dp)); dp[0]=1; int dpt[120000]; for(int i=1;i<=6;i++) { memset(dpt,0,sizeof(dpt)); for(int j=i;j<=nLimit;j++) if(!dp[j]&&dp[j-i]&&dpt[j-i]<bag[i]) { dpt[j]=dpt[j-i]+1; dp[j]=1; } } if(dp[nLimit]) { printf("Can be divided.\n"); } else { printf("Can‘t be divided.\n"); } } printf("\n"); } return 0; }
判断模板:
memset(dp,0,sizeof(dp)); dp[0]=1; int used[120000]; for(int i=1;i<=nKind;i++) { memset(used,0,sizeof(used)); for(int j=weight[i];j<=nLimit;j++) if(!dp[j]&&dp[j-weight[i]]&&used[j-weight[i]]<bag[i]) { used[j]=used[j-weight[i]]+1; dp[j]=1; } }
时间: 2024-11-05 15:57:05