Fork me on GitHub

就决定是你了!

题目来源:https://biancheng.love/contest-ng/index.html#/34/problems

题目描述

Nova君来到神奇宝贝中心,准备从存储机中挑选若干个Pockmon去挑战最后的四天王和联盟冠军。Nova君现在有N只可挑选的Pockmon,对于第 i 只Pockmon,他的体总为 wi ,战斗力为 vi 。现在联盟规定,只能携带总重量为M的Pockmon进行挑战。那么,Nova君要怎么挑选才能使战斗力最强呢?大家肯定会说,这不是个简单的背包问题嘛?嗯,大概。但是现在有个问题,由于某些Pockmon在冒险的途中,和存储机内的其他Pockmon产生了羁绊,有可能对另一只Pokmon产生依赖,非得被依赖的那只被选中才能发挥战斗力,否则只能是个战斗力为0的卖萌生物而已,好在每只Pockmon都很专情,只会依赖一只(或者不依赖)。

PS:

(1) 依赖关系不对称,即,若A依赖B,B不一定依赖A,俗称beitai;

(2) 可能出现这样的情况:A依赖B,B依赖C,C依赖A,俗称love triangle,当然也有可能是多边形(悲伤脸)

(3) 保证不会出现自己依赖自己的情况

输入

多组测试数据(组数不超过10),对于每组数据,输入4行,第一行是两个正整数N,M,表示Pockmon总数和联盟允许的最大重量,第二行包含N个正整数w1,w2...wn,表示第 i 个Pockmon的重量,第三行包含N个正整数v1,v2...vn,表示第 i 个Pockmon的战斗力,第四行包含N个正整数D1,D2...Dn,表示第 i 个Pockmon依赖的Pockmon的序号,如果没有依赖对象,则 Di=0。

PS:输入数据都在INT范围内

输出

对于每组数据,输出一行,表示战斗力的最大值

输入样例

3 10
4 5 6
2 3 4
3 1 2
3 10
4 5 6
2 3 4
0 1 1

输出样例

0
6
代码:
  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 
  4 const int e=505;
  5 int n,m,tmpw=0,tmpn;
  6 int w[e]= {0},v[e]= {0},b[e]= {0},c[e]= {0},f[e][5*e]= {0},d[e]= {0};
  7 bool mapp[e][e]= {0};
  8 
  9 void floride()
 10 {
 11     for(int i=1; i<=n; i++) //弗洛里德判断是否有环;
 12         for(int j=1; j<=n; j++)
 13             for(int k=1; k<=n; k++)
 14                 if(mapp[k][i]==1 && mapp[i][j]==1)
 15                     mapp[k][j]=1;
 16 }
 17 
 18 
 19 void merge()//合点
 20 {
 21     tmpn=n;
 22     for(int i=1; i<=tmpn; i++)
 23         for(int j=1; j<=tmpn; j++)
 24         {
 25             if(mapp[i][j]==1 && mapp[j][i]==1 && i!=j && w[i]>0 && w[j]>0)//如果是新环;
 26             {
 27                 tmpn++;
 28                 v[tmpn]=v[i]+v[j];
 29                 w[tmpn]=w[i]+w[j];
 30                 tmpw--;
 31                 w[i]=tmpw;
 32                 w[j]=tmpw;    //tmpw+tmpn永远等于最开始的n
 33             }
 34 
 35             //如果j依赖的点被合并(是旧环),且j在环里
 36             if(w[d[j]]<0 && w[j]>0 && mapp[j][d[j]]==1 && mapp[j][d[j]]==1)
 37             {
 38                 w[n-w[d[j]]]+=w[j];
 39                 v[n-w[d[j]]]+=v[j];
 40                 w[j]=w[d[j]];
 41             }
 42 
 43             //如果j依赖的点在环里,但是j不在环里
 44             if(w[d[j]]<0 && w[j]>0)
 45                 if((mapp[j][d[j]]==1 && mapp[d[j]][j]==0) || (mapp[j][d[j]]==0 && mapp[d[j]][j]==1))
 46                     d[j]=n-w[d[j]];
 47         }
 48 }
 49 
 50 int  dfs(int x,int k)
 51 {
 52     if(f[x][k]>0)    return(f[x][k]);
 53     if(x==0 || k<=0)    return(0);
 54     //不取x
 55     f[b[x]][k]=dfs(b[x],k);
 56     f[x][k]=f[b[x]][k];
 57     int y=k-w[x];
 58     for(int i=0; i<=y; i++)
 59     {
 60         f[c[x]][y-i]=dfs(c[x],y-i);
 61         f[b[x]][i]=dfs(b[x],i);
 62         f[x][k]=max(f[x][k],v[x]+f[c[x]][y-i]+f[b[x]][i]);
 63     }
 64     return(f[x][k]);
 65 }
 66 
 67 
 68 
 69 int main()
 70 {
 71     while(cin>>n>>m)
 72     {
 73         tmpw=0;
 74         memset(w,0,sizeof(w));
 75         memset(v,0,sizeof(v));
 76         memset(c,0,sizeof(c));
 77         memset(b,0,sizeof(b));
 78         memset(d,0,sizeof(d));
 79         memset(f,0,sizeof(f));
 80         memset(mapp,0,sizeof(mapp));
 81 
 82         for(int i=1; i<=n; i++)
 83             scanf("%d",&w[i]);
 84         for(int i=1; i<=n; i++)
 85             scanf("%d",&v[i]);
 86         for(int i=1; i<=n; i++)
 87         {
 88             int a;
 89             scanf("%d",&a);
 90             d[i]=a;
 91             mapp[a][i]=1;
 92         }
 93 
 94         floride();
 95         merge();
 96 
 97         //多叉转二叉
 98         for(int i=1; i<=tmpn; i++)
 99             if(w[i]>0)
100             {
101                 b[i]=c[d[i]];
102                 c[d[i]]=i;
103             }
104         cout<<dfs(c[0],m)<<endl;
105     }
106 }

 

 
posted @ 2015-12-10 22:32  伊甸一点  阅读(925)  评论(0编辑  收藏  举报