题目链接:点击打开链接
题目大意:略。
解题思路:多重背包。
AC 代码
#include<bits/stdc++.h> #define mem(a,b) memset(a,b,sizeof a) using namespace std; typedef long long ll; const int MAXN = 10000; int dp[MAXN]; int val[MAXN],weight[MAXN],num[MAXN]; int n,m; void ZeroOne_Pack(int val,int weight,int m) { for(int j=m;j>=weight;j--) if(j==weight || dp[j-weight]!=0) // 判断状态是否可转移 dp[j]=max(dp[j],dp[j-weight]+val); } void Complete_Pack(int val,int weight,int m) { for(int j=weight;j<=m;j++) if(j==weight || dp[j-weight]!=0) // 判断状态是否可转移 dp[j]=max(dp[j],dp[j-weight]+val); } int Multi_Pack(int val[],int weight[],int n,int m) { mem(dp,0); for(int i=0;i<n;i++) { if(num[i]*weight[i]>m) { Complete_Pack(val[i],weight[i],m); } else { int k=1; while(k<num[i]) { ZeroOne_Pack(k*val[i],k*weight[i],m); num[i]-=k; k<<=1; } ZeroOne_Pack(num[i]*val[i],num[i]*weight[i],m); } } return dp[m]; } int main() { int n,m=8500; while(~scanf("%d",&n) && n) { // for(int i=0;i<n;i++) // scanf("%d%d",&val[i],&weight[i]); // // int rs=ZeroOne_Pack(val,weight,m); // // // int rs=Complete_Pack(val,weight,m); for(int i=0;i<n;i++) { scanf("%d%d",&weight[i],&num[i]); val[i]=weight[i]; // 根据题意,价值和重量是等价的 } Multi_Pack(val,weight,n,m); sort(dp,dp+m+1); // for(int i=0;i<=m;i++) // { // printf("%d ",dp[i]); // } // puts(""); int i,j=1; for(i=0;i<=m;i++) { if(dp[i]!=0) { if(dp[i]==j) { j++; } else // 匹配不上,说明此时的 j 就是最小称不到的量 { printf("%d\n",j); break; } } } if(i==m+1) // 匹配完了标记,则 dp[m]+1 为最终结果 { printf("%d\n",dp[m]+1); } } return 0; }