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 }
     
  • 相关阅读:
    postman参数化—上个接口返回数据作为下个接口入参
    postman设置token为全局变量
    postman请求https协议接口
    安装VMware 置灰正确解决办法
    Cron 表达式详解
    Jmeter + ant + jenkins轻量级接口自动化测试
    Jmeter CSV 参数化/检查点/断言
    Android专项测试-cpu,流量
    Android专项测试-获取启动时间
    腾讯云测试工程师--面试总结
  • 原文地址:https://www.cnblogs.com/acSzz/p/2629106.html
Copyright © 2011-2022 走看看