码迷,mamicode.com
首页 > 其他好文 > 详细

Starship Troopers

时间:2016-04-11 20:46:06      阅读:242      评论:0      收藏:0      [点我收藏+]

标签:

Starship Troopers

Time Limit : 10000/5000ms (Java/Other)   Memory Limit : 65536/32768K (Java/Other)
Total Submission(s) : 1   Accepted Submission(s) : 1

Font: Times New Roman | Verdana | Georgia

Font Size: ← →

Problem Description

You, the leader of Starship Troopers, are sent to destroy a base of the bugs. The base is built underground. It is actually a huge cavern, which consists of many rooms connected with tunnels. Each room is occupied by some bugs, and their brains hide in some of the rooms. Scientists have just developed a new weapon and want to experiment it on some brains. Your task is to destroy the whole base, and capture as many brains as possible.

To kill all the bugs is always easier than to capture their brains. A map is drawn for you, with all the rooms marked by the amount of bugs inside, and the possibility of containing a brain. The cavern‘s structure is like a tree in such a way that there is one unique path leading to each room from the entrance. To finish the battle as soon as possible, you do not want to wait for the troopers to clear a room before advancing to the next one, instead you have to leave some troopers at each room passed to fight all the bugs inside. The troopers never re-enter a room where they have visited before.

A starship trooper can fight against 20 bugs. Since you do not have enough troopers, you can only take some of the rooms and let the nerve gas do the rest of the job. At the mean time, you should maximize the possibility of capturing a brain. To simplify the problem, just maximize the sum of all the possibilities of containing brains for the taken rooms. Making such a plan is a difficult job. You need the help of a computer.

Input

The input contains several test cases. The first line of each test case contains two integers N (0 < N <= 100) and M (0 <= M <= 100), which are the number of rooms in the cavern and the number of starship troopers you have, respectively. The following N lines give the description of the rooms. Each line contains two non-negative integers -- the amount of bugs inside and the possibility of containing a brain, respectively. The next N - 1 lines give the description of tunnels. Each tunnel is described by two integers, which are the indices of the two rooms it connects. Rooms are numbered from 1 and room 1 is the entrance to the cavern.

The last test case is followed by two -1‘s.

Output

For each test case, print on a single line the maximum sum of all the possibilities of containing brains for the taken rooms.

Sample Input

5 10
50 10
40 10
40 20
65 30
70 30
1 2
1 3
2 4
2 5
1 1
20 7
-1 -1

Sample Output

50
7

 

题目大意:给出一张树形的地图,然后每个节点就是一个洞,每个洞里面有bugs和brain,现在给出我方有m个骑兵,每个骑兵可以消灭20个bugs,经过的洞穴不能再回头,要收服每个洞穴里面的brain就必须消灭每个洞穴里面的全部bugs,求最大的brain

 

思路:树形DP.

对于x个节点来说.dp[x][i]表示在x洞穴用i个骑兵可以收服的brain的数目.其实就是01背包的稍加变形.

for(i=1;i<=n;i++)

  for(int j=m;j>=r;j--)

      for(int k=1;k<=j-r;j++)                                    //k<=j-r 即是:k+r<=j,即等会用于:对于当前节点使用剩下的骑兵k在子节点能够收服的brain值.

              dp[x][j]=max(dp[x][j],dp[x][j-k]+dp[i][k]);// i是x的子节点.这就是说:x节点收服brain的最大值等于:  max(本身初始化的值 ,本身+剩下骑兵的情况下子节点收服的brain值)

 

 

WAY:

这貌似是好早之前讲树形DP的时候遇到的了。

之前就一直不明白,为什么可以dp[x][j]=max(dp[x][j],dp[x][j-k]+dp[i][k])   这样转移呐?DP方程直接翻译过来的含义的确是感觉状态是不合法的。(就是说 DP[x][j-k]里面感觉就包含了DP[i][k]。。。那么i这个son就不只有k个士兵了(对,就是这个疑惑))

但实际上是correct的。

Why?

这样来看:

首先传统的0-1背包,我们先枚举的为一个物品,在自变量里减去了cost[i],在外面加上了value[i]。是这样的吧。

这里的话,我们对于一个root来说,我们DFS他的每一个son的时候(把root的某个son这整个子树处理完),这个son子树其实就是我们枚举的物品。

cost的话,就是我们拿过去的士兵了。value的话,就是son节点的那个DP值了。

所以枚举root的所有子节点,就相当于枚举物品一样的了,都是一个一个处理的。(root的每个son子树处理完了才处理其他的son子树)

 

Code:

#include<stdio.h>
#include<iostream>
using namespace std;
const int MAXN=110;
int N,M;
struct Node
{
    int number,p;
};
Node node[MAXN];//记录结点 
int dp[MAXN][MAXN];//DP,dp[i][j]表示跟结点为i时,用掉j个士兵获得的最大值 
int adj[MAXN][MAXN];//存树 
bool vis[MAXN];//访问标记 

void dfs(int root)//DFS
{
    vis[root]=true;//已经访问 
    int num=(node[root].number+19)/20;//获得该结点需要的士兵数目 
    for(int i=num;i<=M;i++)  dp[root][i]=node[root].p;
    for(int i=1;i<=adj[root][0];i++)
    {
        int u=adj[root][i];
        if(vis[u]) continue;
        dfs(u);
        for(int j=M;j>=num;j--)
        {
            for(int k=1;j+k<=M;k++)
            {
                if(dp[u][k])
                  dp[root][j+k]=max(dp[root][j+k],dp[root][j]+dp[u][k]);
            }    
        }    
    }    
}  
int main()
{
    int b,e;
    while(scanf("%d%d",&N,&M))
    {
        if(N==-1&&M==-1) break;
        memset(vis,false,sizeof(vis));
        memset(dp,0,sizeof(dp));
        memset(adj,0,sizeof(adj));
        for(int i=1;i<=N;i++)
            scanf("%d%d",&node[i].number,&node[i].p);
        for(int i=1;i<N;i++)//存图 
        {
             scanf("%d%d",&b,&e);
             adj[b][0]++;
             adj[b][adj[b][0]]=e;
             adj[e][0]++;
             adj[e][adj[e][0]]=b;
        }
        if(M==0)//这个必需要,有代价为0的房间,M=0则无法获得 
          printf("0\n");
        else
        {
            dfs(1);
            printf("%d\n",dp[1][M]);
        }    

    } 
    return 0;   
}

这个代码,貌似跟我们讲的还是很清楚了!

Starship Troopers

标签:

原文地址:http://www.cnblogs.com/cherry231/p/5379678.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!