2018.11.09【NOIP2006】【洛谷P1064】金明的預算方案(有依賴的揹包問題)
阿新 • • 發佈:2018-11-10
傳送門
解析:
首先我並沒有讀完題。。我也沒有管什麼只有兩個依賴,,我直接寫的最裸的單層依賴的揹包問題。。。(其實依賴下面套分組還比這個要噁心)。
思路:
由於我們直接列舉所有策略,對於一個物品集合是 的,所以我們可以先在集合內部做一次 揹包,注意,為了減小最終的物品個數,可以使用恰好揹包。
然後就是集合與集合之間的分組揹包裸題了。
程式碼:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define re register
#define gc getchar
#define pc putchar
#define cs const
cs int N=65,M=32004;
vector<pair<int,int> > vec[N];
vector<pair<int,int> > item[N];
int v[N],p[N],q[N];
int f[M];
int n, m;
signed main(){
scanf("%d%d",&n,&m);
for(int re i=1;i<=m;++i){
scanf("%d%d%d",&v[i],&p[i],&q[i]);
if(q[i]){
vec[q[i]].push_back(make_pair(v[i],p[i]));
}
}
for(int re i=1;i<=m;++i){
if(!vec[i].empty()){
memset(f,-1,sizeof f);
f[0]=0;
for(int re j=0;j<vec[i].size();++j){
for(int re k=n-v[i];k>=vec[i][j].first;--k){
if((~f[k-vec[i][j].first])&&f[k]<f[k-vec[i][j].first]+vec[i][j].first*vec[i][j].second){
f[k]=f[k-vec[i][j].first]+vec[i][j].first*vec[i][j].second;
}
}
}
for(int re k=n-v[i];k;--k){
if(~f[k]){
item[i].push_back(make_pair(k+v[i],f[k]+v[i]*p[i]));
}
}
}
if(!q[i]){
item[i].push_back(make_pair(v[i],v[i]*p[i]));
}
}
memset(f,0,sizeof f);
for(int re i=1;i<=m;++i)
for(int re k=n;k;--k)
for(int re j=0;j<item[i].size();++j)
if(k>=item[i][j].first)f[k]=max(f[k],f[k-item[i][j].first]+item[i][j].second);
cout<<f[n];
return 0;
}