试题描述 |
ACboy很喜欢玩一种战略游戏,在一个地图上,有N座城堡,每座城堡都有一定的宝物,在每次游戏中ACboy允许攻克M个城堡并获得里面的宝物。但由于地理位置原因,有些城堡不能直接攻克,要攻克这些城堡必须先攻克其他某一个特定的城堡。你能帮ACboy算出要获得尽量多的宝物应该攻克哪M个城堡吗? |
输入格式 |
每个测试实例首先包括2个整数,N,M.(1 <= M <= N <= 200);在接下来的N行里,每行包括2个整数,a,b. 在第 i 行,a 代表要攻克第 i 个城堡必须先攻克第 a 个城堡,如果 a = 0 则代表可以直接攻克第 i 个城堡。b 代表第 i 个城堡的宝物数量, b >= 0。当N = 0, M = 0输入结束。 |
输出格式 |
对于每个测试实例,输出一个整数,代表ACboy攻克M个城堡所获得的最多宝物的数量。 |
输入示例 |
3 2 0 1 0 2 0 3 7 4 2 2 0 1 0 4 2 1 7 1 7 6 2 2 0 0 |
输出示例 |
5 13 |
【分析】
树形dp,这种要求在n个里取m个的我不会用前向星写,所以只好用邻接矩阵了...
【代码】
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 int n,m; 5 int c[320] ,b[320] ,s[320], dp[320][320]; 6 7 int maxx(int a, int b, int c) { 8 int ans=a; 9 if (b>ans) 10 ans=b; 11 if (c>ans) 12 ans=c; 13 return ans; 14 } 15 16 void maketree() { 17 memset(c, 0, sizeof(c)); 18 memset(b, 0, sizeof(b)); 19 memset(s, 0, sizeof(s)); 20 memset(dp, -1, sizeof(dp)); 21 cin >> n >> m; 22 if (n==0 && m==0) 23 exit(0); 24 for(int i=1;i<=n;i++){ 25 int ta,tb; 26 scanf("%d%d",&ta,&tb); 27 s[i]=tb; 28 if(ta==0) ta=n+1; 29 b[i]=c[ta]; 30 c[ta]=i; 31 } 32 } 33 34 void dfs(int x,int y) { 35 if(dp[x][y]>=0) return; 36 if(x==0 || y==0) { dp[x][y]=0;return;} 37 dfs(b[x],y); 38 for(int k=0;k<y;k++){ 39 dfs(b[x],k); 40 dfs(c[x],y-k-1); 41 dp[x][y]=maxx(dp[x][y], dp[b[x]][y], dp[b[x]][k]+dp[c[x]][y-k-1]+s[x]); 42 } 43 return; 44 } 45 46 int main() { 47 while (true) { 48 maketree(); 49 dfs(c[n+1],m); 50 cout << dp[c[n+1]][m] << endl; 51 } 52 return 0; 53 }
时间: 2024-09-29 15:32:21