简要分析:
- 将每个主件和附件进行组合,然后做分组背包
- 坑点:
- 附件有可能比主件更早出现
- 编号实际是指行数,而非第几个组件
代码
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn=10000;
int F[maxn*1000],v[100][5],c[1010][5];//c[]指代价,w[]指价值,T[]指第k组的件数
int T1[100][5],T2[100][5];
int N,V;
inline long long Read(void)
{
int w=0,x=0;
char ch=0;
while(!isdigit(ch))w|=ch=='-',ch=getchar();
while(isdigit(ch)) x=x*10+(ch^48),ch=getchar();
return w?-x:x;
}
int main(void)
{
V=Read(),N=Read();//输入
for(int i=1; i<=N; ++i) T1[i][0]=1;
for(int i=1; i<=N; ++i)
{
int t1=Read(),t2=Read(),t3=Read();//t1为价格,t2为重要的,t3为组别
if(t3==0)//主件
{
T1[i][1]=t1;
T2[i][1]=t2*t1;
}
else
{
T1[t3][0]++;
T1[t3][T1[t3][0]]=t1;
T2[t3][T1[t3][0]]=t2*t1;
}
}
for(int k=1; k<=N; ++k)
{
for(int i=1; i<=T1[k][0]; ++i)
{
if(i==1)
{
c[k][++c[k][0]]=T1[k][i];
v[k][c[k][0]]=T2[k][i];
}
else
{
int now=c[k][0];
for(int j=1; j<=now; ++j)
{
c[k][++c[k][0]]=c[k][j]+T1[k][i];
v[k][c[k][0]]=v[k][j]+T2[k][i];
}
}
}
}
for(int k=1; k<=N; ++k)
{
for(int j=V; j>=0; --j)
{
for(int i=1; i<=c[k][0]; ++i)//第k组第i种方案
{
if(j>=c[k][i])
F[j]=max(F[j],F[j-c[k][i]]+v[k][i]);
}
}
}
printf("%d",F[V]);
return 0;
}