題目地址
金明的題都出爛了怎麼我還在寫。。。依賴性揹包,把主件和它的附件看做一個集合,每個集合的決策只有5種:
1.全部不選
2.選主件
3.選主件和附件1
4.選主件和附件2
5.全選
把主件拉在一個數組計算即珂。
蒟蒻的垃圾碼風:
//2020/2/16 TOSHIBA i3-2328 2.5Hz FILCO聖手2代 百樂V5 晨光K-35
# include <bits/stdc++.h>
using namespace std;
const int N=32010;
int n,m;
int w[N][3];
int c[N][3];
int sonk[N];
int dp[N];
int zhujian[N];
int zk=0;
//vector <int> son[N];
inline int read()
{
int s=0,w=1;
char ch=getchar();
while(!isdigit(ch))
{
if(ch=='-') w=-1;
ch=getchar();
}
while(isdigit(ch))
{
s=(s<<1)+(s<<3)+ch-'0';
ch=getchar();
}
return s*w;
}
void Input()
{
n=read(),m=read();
for(int i=1;i<=m;i++)
{
int _w=read(),_c=read(),_q=read();
if(_q==0)
{
w[i][0]=_w;
c[i][0]=_c;
zhujian[++zk]=i;
}
else
{
++sonk[_q];
w[_q][sonk[_q]]=_w;
c[_q][sonk[_q]]=_c;
}
}
return ;
}
void solve()
{
int P;
for(int i=1;i<=zk;i++)
{
P=zhujian[i];
for(int j=n;j>=w[P][0];j--)
{
dp[j]=max(dp[j],dp[j-w[P][0]]+c[P][0]*w[P][0]); //No choose and Only choose
if(sonk[P]>=1&&j>=w[P][0]+w[P][1]) dp[j]=max(dp[j],dp[j-w[P][0]-w[P][1]]+c[P][0]*w[P][0]+c[P][1]*w[P][1]);
if(sonk[P]>=2&&j>=w[P][0]+w[P][2]) dp[j]=max(dp[j],dp[j-w[P][0]-w[P][2]]+c[P][0]*w[P][0]+c[P][2]*w[P][2]);
if(sonk[P]>=2&&j>=w[P][0]+w[P][1]+w[P][2]) dp[j]=max(dp[j],dp[j-w[P][0]-w[P][1]-w[P][2]]+c[P][0]*w[P][0]+c[P][1]*w[P][1]+c[P][2]*w[P][2]);
}
}
printf("%d\n",dp[n]);
return ;
}
int main(void)
{
Input();
solve();
return 0;
}
/*
每一次對於主件有5種決策:
1.屁都不選
2.選主件
3.選主件+附件1
4.選主件+附件2
5.我全都要
也就是對於每一個主件與附件集合的最優解,枚舉每個集合,得到全局最優
*/