zoukankan      html  css  js  c++  java
  • hdu 4340 Capturing a country(树形 dp) (2012 MultiUniversity Training Contest 5 )

                                                  Capturing a country

                                                                                    Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
                                                                                                              Total Submission(s): 380    Accepted Submission(s): 164


    Problem Description
    Ant and Bob two army want to capture a country. The country is consist of N cities. To capture the city i, it takes Ant A[i] minutes, and Bob needs B[i] minutes to capture city i. Due to the similarity of neighboring cities, If the city i and j are neighboring cities, if Ant has captured city i, then the time for Ant to capture city j is A[j]/2. Of course if Ant has captured city j, then the time for Ant to capture city i is A[i]/2. It is the same for Bob. We define the total time to capture a country be the time to capture city 1 + the time to capture city 2 + ... + the time to capture city N. Now we want to know the minimal total time.
    For simplicity, we assume that there is only one path to go from one city to another city.
     
    Input
    The first line contains a integer N(0<N<100), which is the number of cities.Then following N lines describe A[1], A[2], …, A[N];Then following N lines describe B[1], B[2], …, B[N];Next comes N-1 lines, each contains two integers x, y, meaning that city x and city y are neighboring.
     
    Output
    Just output the minimal total time in a single line.
     
    Sample Input
    3
    1 2 5
    3 8 1
    1 2
    1 3
     
    Sample Output
    3
     
    Source
     
    Recommend
    zhuyuanchen520
     
     
    终于把这道题的题解看明白了,,自己推了好长时间,又看了好长时间,汗。。。。。。。
    题意: 两个人进攻n个城市,这n个城市构成一棵树,可以任意选择一个点开始,攻击已被自己攻击过的点的相邻点,
          时间可以减半,两个人的攻击时间不一,两个人可以同时进行攻击。
    看得是官方解题报告;
    状态:dp[i][j][k] (0 <= i <= n, 0<=j<=1, 0 <= k <= 1) 表示以 i 为根的子树的费用,其中i节点被染成了第j种颜色,且子树中与i染成同一种颜色的与i连通的点集有k个点选取了完整的费用
     
     
    那么 我们就可以得到 状态转移方程;
    1:dp[ i ][ j ][ 0 ] = (所有以 i 为跟的 子树最小花费 的和   ) s   + a[j][i]/2; 
    2:s =  求和  min(dp[ v ][j][0],  dp[v][ 1 - j][1]) v 为 i 的子节点    ;理解:因为 在 1 中  k 值为 0 所以 与 i  连通的点 都没有取到 完整的值 及 其 子树的 k 值也为 0 ;因为  在 1 中  根节点 的颜色是 j  (其子节点 必和其连通),所以,其子树中若要 然 其他的颜色 必有     第一个染 其他颜色的 节点  所以  1 - j  的 k  值 为 1;
     
    3: dp[i][j][1] = min(cost[i][j] + S, cost[i][j]/2 + S + det);
    det = min{dp[v][j][1] - min(dp[v][j][0], dp[v][1-j][1])};
      若 和根节点 连通的(包括根节点本身)含有 第一个  染色 为 j 的节点 ,那么这个节点 要么是 根节点 本身 ,要么 在根节点的子树中,
     若为 根节点 则  dp[ i][j ][1] = cost[i][j] + s (所有以 i 为跟的 子树最小花费 的和  )  ;
    若在根节点的子树中 ,那么这个 节点 要求得必 是 子树中 花费最小的     det 就表示 这个节点的费用的 1/2     假设这个点在 以节点 v 为跟的子树中 (v是 i 的子节点)
    det =   dp[v][j][1] - 这棵子树的最小值    ;这棵子树的最小值为   min(dp[v][j][0], dp[v][1-j][1])    然后 我们 枚举所有的子树 找到 最小的det 就可以了
     
     
     1 #include<cstdio>
     2 #include<cstring>
     3 #include<iostream>
     4 #include<algorithm>
     5 #include<set>
     6 #include<map>
     7 #include<queue>
     8 #include<vector>
     9 #include<string>
    10 #define Min(a,b) a<b?a:b
    11 #define Max(a,b) a>b?a:b
    12 #define CL(a,num) memset(a,num,sizeof(a));
    13 #define maxn  205
    14 #define inf 9999999
    15 #define mx 1<<60
    16 using namespace std;
    17 vector<int>g[maxn];
    18 int dp[maxn][2][2],a[2][maxn],vis[maxn];
    19 void dfs(int k)
    20 {
    21     int i,j;
    22     int  len = g[k].size();
    23     if( len == 0)//  为叶子节点
    24     {
    25         dp[k][0][0] = a[0][k]/2;
    26         dp[k][0][1] = a[0][k];
    27         dp[k][1][0] = a[1][k]/2;
    28         dp[k][1][1] = a[1][k];
    29 
    30 
    31 
    32         return ;
    33     }
    34 
    35 
    36         for( i = 0; i < len ;++i)
    37            dfs(g[k][i]) ;
    38 
    39         for( i = 0;i < 2; ++i)
    40         {
    41             int sum = 0,det = inf ,tmp;
    42             for( j = 0; j < len ;++j)
    43             {
    44                 int w = g[k][j];
    45                 tmp = min(dp[w][i][0],dp[w][1 - i][1]);
    46 
    47 
    48                 sum +=tmp;
    49 
    50                 det = min(det,dp[w][i][1] - tmp);
    51 
    52 
    53             }
    54             dp[k][i][0]  = sum + a[i][k]/2;
    55             dp[k][i][1]  = min(a[i][k] + sum ,a[i][k]/2 + sum + det);
    56         }
    57 
    58 
    59 
    60 }
    61 int main()
    62 {
    63     //freopen("data.in","r",stdin);
    64     int n, i, j,x,y,root;
    65     while(scanf("%d",&n)!=EOF)
    66     {
    67         for(j = 0; j < 2 ;++j)
    68         {
    69             for( i = 1; i <= n ;++i )
    70             scanf("%d",&a[j][i]);
    71         }
    72 
    73 
    74         CL(vis,0);
    75         for(i = 0;i <= n;i++)g[i].clear();
    76         for(i = 0; i < n - 1 ;++i)
    77         {
    78           scanf("%d%d",&x,&y);
    79           if( i ==0) root = x;//建的图是有向图,对解决问题没有影响,树形dp 就是 这样
    80           if(!vis[y])
    81           {
    82               g[x].push_back(y);
    83               vis[x] = 1;
    84           }
    85           else g[y].push_back(x);
    86 
    87         }
    88         CL(dp,0);
    89         dfs(root);
    90         int t1 = dp[root][0][1];
    91         int t2 = dp[root][1][1];
    92 
    93         printf("%d\n",min(t1,t2));
    94     }
    95 
    96 }
     
  • 相关阅读:
    JS实现继承,封装一个extends方法
    JS实现new关键字的功能
    前端常见原生方法的实现(bind,promise,new,extends,深拷贝,函数防抖,函数节流)
    Nodejs ORM框架Sequelize快速入门
    Nodejs ORM框架Sequelize(模型,关联表,事务,循环,及常见问题)
    NodeJs mysql 开启事务
    web开发的跨域问题详解
    docker网络
    docker容器的学习
    路飞学城的部署
  • 原文地址:https://www.cnblogs.com/acSzz/p/2629106.html
Copyright © 2011-2022 走看看