首页 > 代码库 > Laoj P1650 The more, The Better

Laoj P1650 The more, The Better

试题描述
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 }

 

Laoj P1650 The more, The Better