题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2191
裸多重背包。背包拆分后用01背包方法即可得到结果。
直接上代码:
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
int val[2005], wei[2005];
int tot, n, i, sum, dp[2005];
int main()
{
scanf("%d", &tot);
while(tot--)
{
int c;
scanf("%d%d", &sum, &c);
memset(dp, 0, sizeof(dp));
memset(val, 0, sizeof(val));//最坑的就是这里三个数组清零的地方
memset(wei, 0, sizeof(wei));
int x, cnt = 1;
while(c--)
{
int j, k, l;//zhong jiazhi shuliang
int t = 1;
scanf("%d%d%d", &j, &k, &l);
while(l >= t)
{
val[cnt] = k * t;
wei[cnt++] = j * t;
l -= t;
t *= 2;
}
if(l)
{
val[cnt] = k * l;
wei[cnt++] = j * l;
}
}
for(i = 1;i <= cnt;i++)
{
for(int j = sum;j >= wei[i];j--)
{
dp[j] = max(dp[j], dp[j-wei[i]] + val[i]);
}
}
int y = 0;
for(i = 1;i <= sum;i++)
{
if(dp[i] > y)
y = dp[i];
}
printf("%d\n", y);
}
return 0;
}
下面的是直接状态转移而没有拆分的方法,研究中。。
# include <stdio.h>
# include <string.h>
int dp[110] ;
int main ()
{
int T, ans, n, m ;
int p, h, c, i, j ;
scanf ("%d", &T) ;
while (T--)
{
scanf ("%d%d", &m, &n) ;
memset (dp, 0, sizeof(dp)) ;
ans = 0 ;
while (n--)
{
scanf ("%d%d%d", &p, &h, &c) ;
for(i = m ; i>=0 ; i--)
{
for(j = 1 ; j <= c && i+j*p<=m ;j++)
{
if (dp[i+j*p] < dp[i]+j*h)
dp[i+j*p] = dp[i]+j*h ;
if (dp[i+j*p] > ans) ans = dp[i+j*p] ;
}
}
}
printf ("%d\n", ans) ;
}
return 0 ;
}