HDOJ 1011 Starship Troopers

         树上的动态规划第一次做,很纠结也很混乱。其实回过头开一下,也就那么样,过不去的不是自己的知识,只是自己的心理关。嗯,今天抽空整理一下动态规划的思路。

        动态规划适用于最优化问题,同时最优化问题需要具备两个要素:最有子结构和重叠子问题。①在寻找最有子结构的时候,可以遵循共同的模式:
     1>问题的一个解可以是做一个选择。
     2>假定选择已知,要确定哪些子问题随之发生,以及如何递归性的描述子问题空间。
②最有子结构以两种方式变化:
     1>有多少个子问题被使用到原问题的一个最优解中。
     2>在决定一个最优解使用那些子问题时有多少选择。
动态规划的第一步,描述最优解的结构:问题获得最优解的情况无非是,在所有的子节点最优解得和的一个选择。而子问题便是所有子节点的问题的最优解。假设父节点为P,子节点为Cn,则所以P[i]=max(C1[x1]+C2[x2]+C3[x3]+……+Cn[xj])(x1+x2+x3+……+xj=i)。由于以上数据结构并不符合标准的最优解的递归定义。所以不妨换种思考的方式稍微改变一下。该题目的数据结构为树状,此结构之间的关系无非就是父子节点之间的关系,相反,兄弟节点之间的关系并不明显。所以上述结构也可以描述为:
                                                P[i]=max(P[i],P[i-j]+Cn[j])(1=<j<=i,i处理完父节点剩余的trooper的个数)
树状结构自上而下的处理也就是深度优先了,然后理论转化代码即可:
View Code
 1 #include <vector>   
2 using namespace std;
3 #include<stdio.h>
4
5 int roomNumber,trooperNumber;
6 vector<int> path[101];
7 int dp[101][101];
8 bool visited[101];
9 int cost[101];
10 int max(int a,int b)
11 {
12 return a>b?a:b;
13 }
14 void solve(int deep)
15 {
16 visited[deep]=true;
17 for (int i=0;i<path[deep].size();i++)
18 {
19 int value=path[deep][i];
20 if(visited[value]) continue;
21 solve(value);
22 for(int j=trooperNumber-1;j>=cost[deep];j--)
23 for (int index=1;index+j<=trooperNumber;index++)
24 if(dp[value][index])//无意义的点无须计算,因为队伍个数不满足需要
25 dp[deep][j+index]=max(dp[deep][j+index],dp[deep][j]+dp[value][index]);
26 }
27 }
28 int main()
29 {
30 //freopen("Starship Troopers.txt","r",stdin);
31 while (scanf("%d%d",&roomNumber,&trooperNumber)!=EOF)
32 {
33 if(roomNumber==-1&&trooperNumber==-1)
34 break;
35 for (int i=0;i<=roomNumber;i++)
36 {
37 path[i].clear();
38 }
39 memset(dp,0,sizeof(dp));
40 memset(visited,0,sizeof(visited));
41 int tempA;
42 for(int i=1;i<=roomNumber;i++)
43 {
44 scanf("%d%d",&cost[i],&tempA);
45 cost[i]=(cost[i]+19)/20;
46 for (int j=cost[i];j<=trooperNumber;j++)
47 dp[i][j]=tempA;
48 }
49 int tempB;
50 for(int i=1;i<=roomNumber-1;i++)
51 {
52 scanf("%d%d",&tempB,&tempA);
53 path[tempB].push_back(tempA);
54 path[tempA].push_back(tempB);
55 }
56 if(trooperNumber==0)
57 printf("0\n");
58 else
59 {
60 solve(1);
61 printf("%d\n",dp[1][trooperNumber]);
62 }
63 }
64 return 0;
65 }


posted on 2011-09-20 23:33  AdaByron  阅读(497)  评论(0编辑  收藏  举报

导航