题目链接:点击打开链接
题目大意:略。
解题思路:多重背包。
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;
}