您的位置:首页 > 大数据 > 人工智能

hdu 4340 Capturing a country(树形 dp) (2012 Multi-University Training Contest 5 )

2012-08-08 22:01 411 查看

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


[align=left]Problem Description[/align]
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.

[align=left]Input[/align]
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
;Then following N lines describe B[1], B[2], …, B
;Next comes N-1 lines, each contains two integers x, y, meaning that city x and city y are neighboring.

[align=left]Output[/align]
Just output the minimal total time in a single line.

[align=left]Sample Input[/align]

3

1 2 5

3 8 1
1 2

1 3

[align=left]Sample Output[/align]

3

[align=left]Source[/align]
2012 Multi-University Training Contest 5

[align=left]Recommend[/align]
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 就可以了

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<set>
#include<map>
#include<queue>
#include<vector>
#include<string>
#define Min(a,b) a<b?a:b
#define Max(a,b) a>b?a:b
#define CL(a,num) memset(a,num,sizeof(a));
#define maxn  205
#define inf 9999999
#define mx 1<<60
using namespace std;
vector<int>g[maxn];
int dp[maxn][2][2],a[2][maxn],vis[maxn];
void dfs(int k)
{
int i,j;
int  len = g[k].size();
if( len == 0)//  为叶子节点
{
dp[k][0][0] = a[0][k]/2;
dp[k][0][1] = a[0][k];
dp[k][1][0] = a[1][k]/2;
dp[k][1][1] = a[1][k];

return ;
}

for( i = 0; i < len ;++i)
dfs(g[k][i]) ;

for( i = 0;i < 2; ++i)
{
int sum = 0,det = inf ,tmp;
for( j = 0; j < len ;++j)
{
int w = g[k][j];
tmp = min(dp[w][i][0],dp[w][1 - i][1]);

sum +=tmp;

det = min(det,dp[w][i][1] - tmp);

}
dp[k][i][0]  = sum + a[i][k]/2;
dp[k][i][1]  = min(a[i][k] + sum ,a[i][k]/2 + sum + det);
}

}
int main()
{
//freopen("data.in","r",stdin);
int n, i, j,x,y,root;
while(scanf("%d",&n)!=EOF)
{
for(j = 0; j < 2 ;++j)
{
for( i = 1; i <= n ;++i )
scanf("%d",&a[j][i]);
}

CL(vis,0);
for(i = 0;i <= n;i++)g[i].clear();
for(i = 0; i < n - 1 ;++i)
{
scanf("%d%d",&x,&y);
if( i ==0) root = x;//建的图是有向图,对解决问题没有影响,树形dp 就是 这样
if(!vis[y])
{
g[x].push_back(y);
vis[x] = 1;
}
else g[y].push_back(x);

}
CL(dp,0);
dfs(root);
int t1 = dp[root][0][1];
int t2 = dp[root][1][1];

printf("%d\n",min(t1,t2));
}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐