本题是三维的01背包。
题目链接:
http://acm.hit.edu.cn/hoj/problem/view?id=1388
若用dp[i][j][k]表示前i种砖中用了j种砖总含铜量为k的最少费用,那么dp[i][j][k]=min{dp[i-1][j-1][[k-copper[i]]+price[i] , dp[i-1][j][k]};
for(i=0;i<=20;i++)
for(j=0;j<=20000;j++)
dp[i][j] = 超过200000以上的数;
dp[0][0]=0;
for(k=0;k<n;k++)
for(i=20;i>=1;i--)
for(j=20000;j>=copper[k];j--)
dp[i][j]=min(dp[i][j],dp[i-1][j-copper[k]]+price[k]);
注意初始化的问题,由于是取min,则除了0 0 之外取无穷大。
第三维可以使逆序也可以是顺序。第二维必须是逆序。
#include <iostream>
#include <math.h>
#include <stdio.h>
#include <string.h>
#include <queue>
#include <algorithm>
using namespace std;
int c[202];
int w[202];
int f[22][20005];
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
#endif
int n,t;
int h = 0;
while(scanf("%d",&n)!=EOF)
{
h++;
if(h>1)
{
printf("\n");
}
for(int i=0; i<n; i++)
{
scanf(" %d %d",&c[i],&w[i]);
}
scanf("%d",&t);
memset(f,0x3f,sizeof(f));
f[0][0] = 0;
for(int i=0; i<n; i++)
{
for(int k=20; k>=1; k--)
{
for(int j=20002; j>=c[i]; j--)
{
if(f[k][j]<f[k-1][j-c[i]] + w[i])
{
f[k][j] = f[k][j];
}
else
{
f[k][j] = f[k-1][j-c[i]] + w[i];
}
}
}
}
for(int i=0; i<t; i++)
{
int m,cMin,cMax;
int ans = 0x3f3f3f3f;
int flag = 0;
scanf(" %d %d %d",&m,&cMin,&cMax);
for(int j=m*cMin; j<=m*cMax; j++)
{
if(f[m][j]<ans)
{
ans = f[m][j];
flag = 1;
}
}
if(m>n || flag == 0)
{
printf("impossible\n");
}
else
{
printf("%d\n",ans);
}
}
}
return 0;
}