01背包题目
问题描述:有N件物品和一个容量为V的背包。第i件物品的费用是c[i],价值是w[i]。求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大。
特点:每种物品仅有一件,可以选择放或不放。
//dp[i][j]表示前i件物品恰放入一个容量为j的背包可以获得的最大价值
①for(int i =1;i<=n;i++)
{
for(int j=1;j<=V;j++) dp[i][j]=dp[i-1][j];
for(int j=weight[i];j<=V;j++)
{
dp[i][j]=max(dp[i-1][j],dp[i-1][j-weight[i]]+value[i]);
}
}
②int now=1,pre=0;
for(int i=1;i<=n;i++)
{
for(int j=weight[i];j<=V;j++)
{
dp[now][j]=max(dp[pre][j],dp[pre][j-weight[i]]+value[i]);
}
}
③for(int i=1;i<=n;i++)
{
for(int j=V;j>=weight[i];j--)
{
dp[j]=max(dp[j],dp[j-weigth[i]]+value[i];
}
}
HDU2546:饭卡
http://acm.hdu.edu.cn/showproblem.php?pid=2546
#include
using namespace std;
const int maxn = 1e3+5;
int main()
{
int n,m;
int dp[maxn],a[maxn];
while(cin>>n)
{
if(n==0) break;
memset(dp,0,sizeof(dp));
for(int i=1;i<=n;i++)
{
cin>>a[i];
}
sort(a+1,a+1+n);
cin>>m;
if(m<5)
{
cout<=a[i];j--)
{
dp[j]=max(dp[j],dp[j-a[i]]+a[i]);
}
}
cout<
HDU1171:BigEvent in HDU
http://acm.hdu.edu.cn/showproblem.php?pid=1171
#include
using namespace std;
int val[5005],dp[255555];
int n,i,j,a,b,l,sum;
int main()
{
while(~scanf("%d",&n)&&n>0)
{
memset(val,0,sizeof(val));
memset(dp,0,sizeof(dp));
sum = 0;
for(i=0;i=val[i];j--)//01背包
{
dp[j]=max(dp[j],dp[j-val[i]]+val[i]);
}
}
printf("%d %d\n",sum-dp[sum/2],dp[sum/2]);
}
return 0;
}
HDU2602:BoneCollector (模板题)
http://acm.hdu.edu.cn/showproblem.php?pid=2602
#include
using namespace std;
int i,j,k,t,n,m,v;
int dp[1006],c[1006],w[1006];
int main()
{
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&v);
for(i=1;i<=n;i++)
scanf("%d",&w[i]);
for(i=1;i<=n;i++)
scanf("%d",&c[i]);
memset(dp,0,sizeof(dp));
for(i=1;i<=n;i++)
{
for(j=c[i];j<=v;j++)
{
dp[j]=max(dp[j],dp[j-c[i]]+w[i]);
}
for(k=1;k<=v;k++)
printf("%d ",dp[k]);
printf("\n");
}
printf("%d\n",dp[v]);
}
return 0;
}
HDU2639:BoneCollector II(01背包第k优解)
http://acm.hdu.edu.cn/showproblem.php?pid=2639
HDU2955:Robberies
http://acm.hdu.edu.cn/showproblem.php?pid=2955
HDU3466:ProudMerchants
http://acm.hdu.edu.cn/showproblem.php?pid=3466
HDU1864:最大报销额
http://acm.hdu.edu.cn/showproblem.php?pid=1864
完全背包题目
题目描述:有N种物品和一个容量为V的背包,每种物品都有无限件可用。第i种物品的费用是c[i],价值是w[i]。求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大。
//完全背包
for(int i=1;i<=n;i++)
{
for(int j=weight[i];j>=V;j++)//当前状态能从上一个状态转移过来,所以是正遍历
{
dp[j]=max(dp[j],dp[j-weight[i]]+value[i]);
}
}
Hdu 1114:
http://acm.hdu.edu.cn/showproblem.php?pid=1114
#include
using namespace std;
const int N=1000000+50,inf=1e9+7;
int t,x,y,n,W;
int v[N],w[N],dp[N];
int main()
{
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&x,&y);
W=y-x;
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d%d",&v[i],&w[i]);
}
for(int i=1;i<=W;i++)
{
dp[i]=inf;
for(int i=1;i<=n;i++)
{
for(int j=w[i];j<=W;j++)
{
dp[j]=min(dp[j],dp[j-w[i]]+v[i]);
}
}
}
if(dp[W]!=inf) printf("The minimum amount of money in the piggy-bank is %d.\n",dp[W]);
else printf("This is impossible.\n");
}
return 0;
}
Hdu 1248:
http://acm.hdu.edu.cn/showproblem.php?pid=1248
#include
using namespace std;
int value[3]={150,200,350};
int main()
{
int T;
while(~scanf("%d",&T) &&T!= 0)
{
int dp[10001];
int n;
for(int i=0;i
Hdu2159:
http://acm.hdu.edu.cn/showproblem.php?pid=2159
#include
#include
using namespace std;
int a[105], b[105], dp[105][105];
int main()
{
int n, m, k, s;
while(cin >> n >> m >> k >> s)
{
for(int i = 0; i < k; ++i)
cin >> a[i] >> b[i];
memset(dp, 0, sizeof(dp));
for(int i = 0; i < k; ++i)
for(int j = 1; j <= s; ++j)
for(int p = b[i]; p <= m; ++p)
dp[p][j]= max(dp[p][j], dp[p-b[i]][j-1]+a[i]);
if(dp[m][s] < n)
cout << "-1" << endl;
else
{
for(int i = 0; i <= m; ++i)
{
if(dp[i][s] >= n)
{
cout << m-i << endl;
break;
}
}
}
}
return 0;
}
多重背包
问题描述:有N种物品和一个容量为V的背包。第i种物品最多有n[i]件可用,每件费用是c[i],价值是w[i]。求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大。
这题目和完全背包问题很类似。基本的方程只需将完全背包问题的方程略微一改即可,因为对于第i种物品有n[i]+1种策略:取0件,取1件……取 n[i]件。令f[i][v]表示前i种物品恰放入一个容量为v的背包的最大权值,则:f[i][v]=max{f[i-1][v-kc[i]]+ kw[i]|0<=k<=n[i]}。复杂度是O(V*∑n[i])。
for(int i=1;i<=n;i++)
{
for(int j=weight[i];j<=V;j++)
{
for(int k=V;k>=j*weight[i];k--)
{
dp[i][k]=max(dp[i-1][k],dp[i-1][k-j*weight[i]]+j*value[i]);
}
}
}
Hdu2191:
http://acm.hdu.edu.cn/showproblem.php?pid=2191
#include
using namespace std;
const int maxn=500;
int n,m,w[maxn],c[maxn],num[maxn],dp[maxn];
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
int cur=0;
scanf("%d%d",&n,&m);
for(int i=0;i=k*w[i])
dp[j]=max(dp[j],dp[j-k*w[i]]+c[i]*k);
ans=max(ans,dp[j]);
}
}
printf("%d\n",ans);
}
return 0;
}
Hdu 2844:
http://acm.hdu.edu.cn/showproblem.php?pid=2844
Poj 1014
http://poj.org/problem?id=1014