poj 2152 Fire(树形dp)
来源:互联网 发布:slmmsk软件下载 编辑:程序博客网 时间:2024/04/27 23:56
Description
Country Z has N cities, which are numbered from 1 to N. Cities are connected by highways, and there is exact one path between two different cities. Recently country Z often caught fire, so the government decided to build some firehouses in some cities. Build a firehouse in city K cost W(K). W for different cities may be different. If there is not firehouse in city K, the distance between it and the nearest city which has a firehouse, can’t be more than D(K). D for different cities also may be different. To save money, the government wants you to calculate the minimum cost to build firehouses.
Input
The first line of input contains a single integer T representing the number of test cases. The following T blocks each represents a test case.
The first line of each block contains an integer N (1 < N <= 1000). The second line contains N numbers separated by one or more blanks. The I-th number means W(I) (0 < W(I) <= 10000). The third line contains N numbers separated by one or more blanks. The I-th number means D(I) (0 <= D(I) <= 10000). The following N-1 lines each contains three integers u, v, L (1 <= u, v <= N,0 < L <= 1000), which means there is a highway between city u and v of length L.
Output
For each test case output the minimum cost on a single line.
Sample Input
5
5
1 1 1 1 1
1 1 1 1 1
1 2 1
2 3 1
3 4 1
4 5 1
5
1 1 1 1 1
2 1 1 1 2
1 2 1
2 3 1
3 4 1
4 5 1
5
1 1 3 1 1
2 1 1 1 2
1 2 1
2 3 1
3 4 1
4 5 1
4
2 1 1 1
3 4 3 2
1 2 3
1 3 3
1 4 2
4
4 1 1 1
3 4 3 2
1 2 3
1 3 3
1 4 2
Sample Output
2
1
2
2
3
啊……这道题目,刚开始的时候想简单了,最后递推式写着写着就乱了根本推不出来,后来百度了一下发现自己思路差的还是有点远……通过看论文及别人的题解,最后还是和学长讨论了一下才理解的。
关于这道题,在陈启峰2006年的《一张一弛,解题之道 ——“约制、放宽”方法在解题中的应用》论文中以例题出现,有详细的讲解。其中关于dp[i][j]的状态,以及best数组的应用很值得借鉴。(我现在有点迟疑……)
啊!!看题解发现,题解中对于best数组的定义和论文中并不一样。。。
晕……这两种其实真的算是不同的思路了……
其中dp[i][j]表示的状态是:i节点依赖于j节点(j节点必有一个消防站),同时以i为根节点的子树中所有节点都已有相应的消防站并达到最优解。
best[i]则表示以i为根节点,所有子树都有可依赖的消防站,并使费用达到最小(注意:和论文中提到不同的……i的子树中这些节点所依赖的节点不一定仍在i的子树中)
同时我们以dis数组辅助,对于每一次的节点k都进行一次更新,dis[i]代表节点i到k的距离。
这个神奇的状态转移方程……你要是像我一样看着论文来理解你就输了,因为这两者对best的定义都不一样。。。
dp[now][j]=w[j]+sum(min(dp[i][j]-w[j],best[i])) // i为j的孩子。
best[now]=min(dp[now][j],best[now]) //遍历j进行best[now]的更新。
dp[now][j]首先被赋一个初值w[j],因为j节点一定会修建,之后遍历now的子节点i,对于每一个节点i,要取到其最优值,讲道理应该是best[i](我们对best[i]的定义,并且best[i]是从子节点一层层更新上来的,所以可以保证最优),但是因为dp[now][j]一定会在j处修建一个消防站,而dp[i][j]的含义是i依赖于j,其他点达到最优,虽然dp[i][j]>=best[i],但是由于我们此时j一定会修建,所以可以不考虑j处修建的费用,我们此时便可取min(dp[i][j]-w[j],best[i])。
我的天……我都不知道怎么说了……要不是学长的提醒,一直没看出来论文和题解中状态的不同,这也是我困惑了这么长时间的原因……哎……突然又觉得做这道题似乎不去看论文的思路比较好。。。
以下是AC代码:
#include <iostream>#include <cstdio>#include <cstring>#include <string>#include <vector>#include <algorithm>#define maxn 1010#define inf 0x3f3f3f3fusing namespace std;struct node{ int to,len; node(){}; node(int _to,int _len):to(_to),len(_len) {};};vector<node> g[maxn];int dp[maxn][maxn],dis[maxn],d[maxn],w[maxn],best[maxn];int t,n;void getdis(int now,int fa,int dist){ dis[now]=dist; for(int i=0;i<g[now].size();i++) { int v=g[now][i].to; if(v==fa) continue; int len=g[now][i].len; getdis(v,now,len+dist); }}void dfs(int now,int fa){ for(int i=0;i<g[now].size();i++) { int v=g[now][i].to; if(v==fa) continue; dfs(v,now); } getdis(now,0,0); for(int i=1;i<=n;i++) { if(dis[i]>d[now]) dp[now][i]=inf; else{ dp[now][i]=w[i]; for(int j=0;j<g[now].size();j++) { int v=g[now][j].to; if(v==fa) continue; dp[now][i]+=min(best[v],dp[v][i]-w[i]); } best[now]=min(best[now],dp[now][i]); } }}int main(){ cin>>t; while(t--) { cin>>n; for(int i=0;i<=n;i++) g[i].clear(); memset(best,0x3f,sizeof(best)); for(int i=1;i<=n;i++) cin>>w[i]; for(int i=1;i<=n;i++) cin>>d[i]; for(int i=1;i<=n-1;i++) { int a,b,v; cin>>a>>b>>v; g[a].push_back(node(b,v)); g[b].push_back(node(a,v)); } dfs(1,0); cout<<best[1]<<endl; } return 0;}
- ***POJ 2152 - Fire(树形DP)
- poj 2152 Fire(树形dp)
- poj 2152 Fire (树形dp)
- 【POJ 2152】Fire【树形DP】
- Fire - POJ 2152 树形dp
- poj 2152 Fire 树形dp
- poj 2152 Fire 树形DP
- 【树形DP】 POJ 2152 Fire
- [树形DP] POJ 2152 Fire
- POJ 2152 Fire(依赖型树形dp)
- Poj 2152 Fire (DP_树形DP)
- poj 2152 Fire - 经典树形dp
- POJ 2152 Fire (树形DP,有趣)
- 树形dp(Fire)
- poj 2152 Fire dp 树形dp+暴力 ★★
- POJ 2152 Fire 很难的树形DP
- poj 2152 Fire 树形DP ★★★★
- POJ2152 Fire 树形DP
- Uva120 Stacks of Flapjacks【构造法】【例题8-1】
- 通过RBM实现协同过滤
- MAC系统操作指令汇总
- 解决html用js或者jq跨域请求报错的问题。我的ssm服务器!
- MVC设计模式
- poj 2152 Fire(树形dp)
- hdu4283 You Are the One 区间DP
- mediaPlayer的使用(内存卡与内存中读取资源)
- Java输入输出流
- Struts2的拦截器
- 写了个小东西
- 数组的表示
- 内容提供者之读取手机联系人
- 备忘mybatis使用