题目链接:https://vjudge.net/problem/HDU-5410
以前学习过一种解法。
用完全背包的方法来做多重背包的题目。
博客链接:http://blog.csdn.net/xl2015190026/article/details/54583263
其中用到了一个used数组。
由于转移只有一种,而且前置状态越大越好,所以这种做法是正确的。
一开始没有想明白,所以就将这个方法搬过来直接用了。
具体就是说:
用used数组来标记是否已经使用过,如果没使用过,那就用A[i]+B[i]转移,否则就用A[i]转移。
这个方法是错误的,因为转移有两种,但前置状态只有一个,所以前置状态不是越大越好的,应该分别记录两种转移所对应的两个前置状态才对。
可能很多时候都会出现这种简单题被卡的情况。
这大概就能说明自己的熟练度还不够了(基础不够熟练吧)。
解决办法:
平时就应该多做这种散题、套题训练,查漏补缺。
平时就应该把很多细节思考清楚。
比赛时可以考虑换一个思路。
代码
#include<stdio.h>
#include<algorithm>
using namespace std;
const int maxn = 1010;
const int maxm = 2010;
int M,N;
int W[maxn],A[maxn],B[maxn];
int dp[2][maxm];
int cur;
void read()
{
scanf("%d %d",&M,&N);
for(int i=1;i<=N;i++)
scanf("%d %d %d",W+i,A+i,B+i);
for(int i=0;i<=M;i++)
dp[0][i]=dp[1][i]=0;
cur=0;
}
void debug(int x)
{
printf("前%d\n",x);
for(int i=0;i<=M;i++)
printf("%d ",dp[cur][i]);
puts("");
puts("---");
}
void solve()
{
read();
for(int i=1;i<=N;i++)
{
for(int j=1;j<=M;j++)
{
dp[cur][j]=dp[cur^1][j];
dp[cur][j]=max(dp[cur][j],dp[cur][j-1]);
if(j>=W[i])
{
dp[cur][j]=max(dp[cur][j],dp[cur][j-W[i]]+A[i]);
dp[cur][j]=max(dp[cur][j],dp[cur^1][j-W[i]]+A[i]+B[i]);
}
}
//debug(i);
cur^=1;
}
printf("%d\n",max(dp[cur][M],dp[cur^1][M]));
}
int main()
{
int T;
scanf("%d",&T);
while(T--) solve();
return 0;
}