因为每个主件只有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;
}