SDNU 1352.Stalingrad: Enemy at the Gates 树状DP


1352.Stalingrad: Enemy at the Gates

Description
    Enemy at the gates!
    King James let you be the general of the Royal Army to defend the country, you know the fighting capacity of the soldiers, you need to maximizing the total fingting capacity of the Royal Army, of course, he can also send himself. The limit is, if one soldier was sent to the war, then his superior can not be sent, and the general has no superior.

    Your task is to help the general know the maximum fingting capacity there will be.


Input
    The 1st line, an integer N ( 1<=N<=6000 ), the number of soldiers in the Royal Army.
    The next N lines, each line has an integer x ( -128<=x<=127 ), the fighting capacity of the i-th soldier.

    Then, there are multiple lines and these lines ending with 0 0, each line has two integers, L and K, said that the K-th soldier is the L-th soldier's superior.


Output

    One integer, the maximum fingting capacity.


Sample Input

11
2
3
1
1
1
4
1
5
-2
5
2
1 3
2 3
3 5
6 4
9 6
10 7
7 4
8 4
11 8
4 5
0 0

Sample Output

20


    题意是说有n个士兵,下面n行把他们各自的能力表示出来,然后下面再跟的是第l个士兵的上级是第k个士兵。在派遣的时候如果派了一个士兵,那么这个士兵的上一级就不能再派遣,问最大派遣的能力是多少。

    以前也做过类似的题,看题意很清楚这是个树状DP的题目,然后把派遣和不派遣的能力都用dp数组排出来就好了。不过.....虽然做过但是还是不会建树= =好吧,一直是自己的薄弱点,这次再写这个博客出来的原因也是该好好学学建树了,于是上网又学了下,下面代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int n;
int father[6005];
int dp[6005][2];
bool vis[6005];

int dfs(int root)
{
     int i,j;
     vis[root]=1;
     for(i=1;i<=n;i++)
     {
          if(!vis[i]&&father[i]==root)
          {
               dfs(i);
               dp[root][1]=dp[root][1]+dp[i][0];
               dp[root][0]=dp[root][0]+max(dp[i][0],dp[i][1]);
          }
     }
     return 0;
}

int main()
{
     int i,j,l,k,root;
     while(scanf("%d",&n)!=EOF)
     {
          root=0;
          memset(vis,0,sizeof(vis));
          memset(father,0,sizeof(father));
          memset(dp,0,sizeof(dp));
          for(i=1;i<=n;i++)
          {
               scanf("%d",&dp[i][1]);
          }
          while(scanf("%d%d",&l,&k))
          {
               if(l==0&&k==0)
                    break;
               father[l]=k;
               if(father[k]==0)
                    root=k;
          }
          dfs(root);
          cout<<max(dp[root][0],dp[root][1])<<endl;
     }
     return 0;
}


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值