usc oj 1615 The contest

来源:互联网 发布:印度超越 知乎 编辑:程序博客网 时间:2024/05/21 03:25

题意:背包问题,加了一个限制条件:某几个物品会相互限制,限制的集合里的物品只能选一件

思路:加一个并查集,把集合当成一个物品,像01背包那样记忆化搜索即可。

#include <iostream>#include <cstdio>#include <vector>#include <algorithm>#include <cstring>using namespace std;struct goods{    int v,c;}g[1100];vector<int> vc[1100];int dp[1100][1100];int pa[1100];bool vis[1100],mark[1100];int pre;int dfs(int w,int cnt,int m){    int ans = 0;    if(dp[cnt][w] != -1) ans = dp[cnt][w];    else if(cnt == m){        if(cnt <= pre){            for(int i = 0;i<vc[cnt].size();i++){                int index = vc[cnt][i];                if(w>=g[index].c) ans=max(ans,g[index].v);            }        }        else{            if(w >= g[vc[cnt][0]].c)                ans += g[vc[cnt][0]].v;        }    }    else{        if(cnt <= pre){            ans = dfs(w,cnt+1,m);            for(int i =0;i<vc[cnt].size();i++){                int index = vc[cnt][i];                if(w >= g[index].c){                    ans = max(ans,dfs(w-g[index].c,cnt+1,m)+g[index].v);                }            }        }        else{            if(w >= g[vc[cnt][0]].c)                ans = max(dfs(w,cnt+1,m),dfs(w- g[vc[cnt][0]].c,cnt+1,m) + g[vc[cnt][0]].v);            else                ans = dfs(w,cnt+1,m);        }    }    return dp[cnt][w] = ans;}int find(int x){    if(pa[x] == x)return x;    return pa[x] = find(pa[x]);}int main(){    int n,Wmax,k;    while(~scanf("%d%d%d",&n,&Wmax,&k)){        memset(dp,-1,sizeof dp);        memset(mark,false,sizeof mark);        memset(vis,false,sizeof vis);        for(int i=1;i<=n;i++) vc[i].clear(),pa[i]=i;        for(int i=1;i<=n;i++) scanf("%d%d",&g[i].v,&g[i].c);        for(int i=1;i<=k;i++){            int a,b;scanf("%d%d",&a,&b);            mark[a] = mark[b]=true;            int x = find(a);int y = find(b);            if(x != y) pa[x] = y;        }        int m = 1;        for(int i=1;i<=n;i++){            int x = find(i);            if(vis[x]) continue; vis[x] = true;            if(!mark[i]) continue;            for(int j =1;j<=n;j++){                int y = find(j);                if(x == y) vc[m].push_back(j);            }            m++;        }        pre = --m;        for(int i=1;i<=n;i++){            if(!mark[i]) vc[++m].push_back(i);        }        printf("%d\n",dfs(Wmax,1,m));    }    return 0;}


0 0
原创粉丝点击