因为每个主件只有0~2个附件,并且每个附件没有附件
val[66][3], wei[66][3]//0表示主件i,1表示主件i的第一个附件,2表示主件i的第二个附件
*************************************************************************
状态转移
1、选择不装
2、选择装且只装主件
3、选择装主件和第1个附件
4、选择装主件和第2个附件
5、选择装主件和第1和2个附件
*************************************************************************
#include <cstdio> #include <algorithm> using namespace std; int n, m; int dp[32010]={0}; int val[66][3]={0}, wei[66][3]={0}; int main() { int i, j, v, p, q; scanf("%d %d", &n, &m); for(i = 1; i <= m; ++i) { scanf("%d %d %d", &v, &p, &q); if(!q) val[i][0]=v*p, wei[i][0]=v;//如果是主件 else if(!val[q][1]) val[q][1]=v*p, wei[q][1]=v;//如果是主件p的第一个附件 else val[q][2]=v*p, wei[q][2]=v;//否则就是主件p的第2个附件 } for(i = 1; i <= m; ++i) { for(j = n; j >= 1; --j) { if(j >= wei[i][0]) //只装主件 dp[j]=max(dp[j], dp[j-wei[i][0]]+val[i][0]); if(j >= wei[i][0]+wei[i][1])//装主件和附件1 dp[j]=max(dp[j], dp[j-wei[i][0]-wei[i][1]]+val[i][0]+val[i][1]); if(j >= wei[i][0]+wei[i][2])//只装主件和附件2 dp[j]=max(dp[j], dp[j-wei[i][0]-wei[i][2]]+val[i][0]+val[i][2]); if(j >= wei[i][0]+wei[i][1]+wei[i][2]) dp[j]=max(dp[j], dp[j-wei[i][0]-wei[i][1]-wei[i][2]]+val[i][0]+val[i][1]+val[i][2]); } } printf("%d\n", dp[n]); return 0; }