VijosP1250:分组背包
背景
Wind设计了很多机器人。但是它们都认为自己是最强的,于是,一场比赛开始了~
描述
机器人们都想知道谁是最勇敢的,于是它们比赛搬运一些物品。
它们到了一个仓库,里面有n个物品,每个物品都有一个价值Pi和重量Wi,但是有些物品放在一起会爆炸,并且爆炸具有传递性。(a和b会爆炸、b和c会爆炸则a和c会爆炸)
机器人们可不想因此损失自己好不容易从Wind那里敲诈来的装备,于是它们想知道在能力范围内,它们最多可以拿多少价值的物品。
你能帮助它们吗?
格式
输入格式
每组测试数据
第1行为n,Wmax,k(0<=n,Wmax,k<=1000)
接下来n行,为每个物品的Pi,Wi(0<=Pi<=1000,1<=Wi<=10,均为整数)
再接下来k行,每行2个数字a,b表示a和b会发生爆炸
输出格式
对每组数据输出1行
为最大可能价值
输入:
3 10 1
100 1
200 5
10 5
1 2
输出:
210
思路:分组背包模板题
#include<cstdio> #include<cstring> #include<algorithm> #include<vector> using namespace std; const int MAXN=1005; int n,W,k; int v[MAXN],w[MAXN]; int par[MAXN]; int prep() { for(int i=0;i<MAXN;i++) { par[i]=i; } } int fnd(int x) { if(par[x]==x) { return x; } return par[x]=fnd(par[x]); } void unite(int x,int y) { int a=fnd(x); int b=fnd(y); par[a]=b; } bool same(int x,int y) { return fnd(x)==fnd(y); } int dp[MAXN]; vector<int> vec[MAXN]; int main() { scanf("%d%d%d",&n,&W,&k); for(int i=0;i<n;i++) { scanf("%d%d",&v[i],&w[i]); } prep(); for(int i=0;i<k;i++) { int x,y; scanf("%d%d",&x,&y); x--,y--; unite(x,y); } for(int i=0;i<n;i++) { int root=fnd(i); vec[root].push_back(i); } for(int k=0;k<n;k++) { if(vec[k].size()==0) { continue; } for(int j=W;j>=0;j--) for(int i=0;i<vec[k].size();i++) { int x=vec[k][i]; if(j>=w[x]) dp[j]=max(dp[j],dp[j-w[x]]+v[x]); } } printf("%d\n",dp[W]); return 0; }