hihoCoder 1035 自驾旅行 树形DP
来源:互联网 发布:淘宝女装级别最高 编辑:程序博客网 时间:2024/04/29 09:52
题目链接:http://hihocoder.com/problemset/problem/1035
题目显然是一个树形DP,我们用dp[ i ][ j ]表示已经询问了子树i的所有关键节点,人车的一个状态。其中
j==0:人去,不管人是否回来
j==1:人去,人一定要回来
j==2:人车都去,人车都要回来
j==3:人车都去,人一定要回来,车不管
j==4:人车都去,不管人车最后是否回来。
注意,这里显然有 dp[i][1]>=dp[i][0] ,dp[i][1]>=dp[i][2]>=dp[i][3]>=dp[i][4]
我们先考虑比较容易计算的,我们记人走边(fa,son)的花费为w1(fa,son),车为w2(fa,son),显然
- dp[fa][1] = ∑ dp[son][1] + 2*w1(fa,son)
- dp[fa][2] = ∑ min( dp[son][1] +2* w1(fa,son) , dp[son][2] + 2*w2(fa,son) )
对dp[fa][0],其实就是有一个边选择为 dp[son][0] + w1(fa,son) 而其他的都选择 dp[son][1] + 2*w1(fa,son);或者都选后者,我们记
- temp = min(dp[son][0] - dp[son][1] - w1(fa,son) ),temp = min(temp,0)
- 则 dp[fa][0] = dp[fa][1] + temp;
dp[fa][3]的决策方式,其实就是一个选择 w2(fa,son) + dp[son][3] + w1(fa,son) ,其他的选t2,或者都选t2,这样我们得到dp[fa][3]的转移方程
- t3=0,t3=min( t3 , w1(fa,son)+ w2(fa,son)+ dp[son][3] - t2 );
- dp[fa][3] = dp[fa][2] + t3;
1、走最后一棵子树时,还有车
这样的情况还是很好计算的,最后一棵子树的选择是 min( w1(fa,son) + dp[son][0] , w2(fa,son) + dp[son][4] ) 而其他选择都是t2。或者全部选择t2。
2、走最后一棵子树时,没有车了。
这种情况大概就是,最后一棵子树的决策是w1(fa,son)+w2(fa,son)+dp[son][3];其他的,某一棵子树,人车走下去,然后只有人回来了,剩下的决策是t2。
这个情况是最麻烦的,因为有两棵特殊的子树,我们类似上面的差值统计的时候,要避免两个差值代表同一个子树。为了解决这个问题,我最开始的方法是,先后将两个差值的优先级设为不同,这样统计的话,可以避免重复子树。但是因为顺序处理没处理好,我的代码最开始有BUG。但是因为能A这题,所以我没注意到。
这里多谢swwlqw的指点,这个问题现在已经改正。
我们记
- ff1 = w1(fa,son)+ w2(fa,son)+ dp[son][3] - t2;
- ff2 = w1(fa,son)+ dp[son][0] - t2;
//#pragma comment(linker, "/STACK:102400000,102400000")#include<cstdio>#include<cstring>#include<vector>#include<queue>#include<cmath>#include<cctype>#include<string>#include<algorithm>#include<iostream>#include<ctime>#include<map>#include<set>using namespace std;#define MP(x,y) make_pair((x),(y))#define PB(x) push_back(x)typedef long long LL;//typedef unsigned __int64 ULL;/* ****************** */const int INF=100011122;const double INFF=1e100;const double eps=1e-8;const int mod=1000000007;const int NN=1000010;const int MM=1000010;/* ****************** */struct G{ int v,w1,w2,next;}E[NN*2];int p[NN],T;bool vis[NN];LL dp[NN][5];int si[NN];void add(int u,int v,int w1,int w2){ E[T].v=v; E[T].w1=w1; E[T].w2=w2; E[T].next=p[u]; p[u]=T++;}void dfs(int u,int fa){ int i,v; si[u]=vis[u]; LL temp=0,t2,t3=0,t41=0; LL f1,f2,ff1,ff2; int match = -1; f1=f2=1LL<<50; dp[u][1]=0; dp[u][2]=0; dp[u][4]=0; for(i=p[u];i+1;i=E[i].next) { v=E[i].v; if(v==fa)continue; dfs(v,u); si[u]+=si[v]; if(si[v]>0) { temp=min(temp,dp[v][0]-dp[v][1]-E[i].w1); dp[u][1]+=dp[v][1]+E[i].w1*2; t2=min(dp[v][1]+E[i].w1*2,dp[v][2]+E[i].w2*2); dp[u][2]+=t2; t3=min(t3,E[i].w1+E[i].w2+dp[v][3]-t2); dp[u][4]+=t2; t41=min(t41, min(dp[v][0]+E[i].w1,dp[v][4]+E[i].w2) - t2 ); ff1=E[i].w1+E[i].w2+dp[v][3]-t2; if(ff1<f1) { match = v; f2 = f1; f1 = ff1; } else f2=min(f2,ff1); } } dp[u][0]=dp[u][1]+temp; dp[u][3]=dp[u][2]+t3; dp[u][4]+=t41; dp[u][4]=min(dp[u][4],dp[u][3]); for(i=p[u];i+1;i=E[i].next) { v=E[i].v; if(v==fa)continue; if(si[v]>0) { t2=min(dp[v][1]+E[i].w1*2,dp[v][2]+E[i].w2*2); ff2=E[i].w1+dp[v][0]-t2; if(v==match) dp[u][4] = min(dp[u][4], dp[u][2] + f2 + ff2); else dp[u][4] = min(dp[u][4], dp[u][2] + f1 + ff2); } }}int main(){ int n,m,i,u,v,w1,w2; while(scanf("%d",&n)!=EOF) { memset(p,-1,sizeof(p)); T=0; memset(vis,false,sizeof(vis)); for(i=1;i<n;i++) { scanf("%d%d%d%d",&u,&v,&w1,&w2); add(u,v,w1,w2); add(v,u,w1,w2); } scanf("%d",&m); for(i=1;i<=m;i++) { scanf("%d",&u); vis[u]=true; } dfs(1,-1); cout<<min(dp[1][0],dp[1][4])<<endl; } return 0;}
- hihoCoder 1035 自驾旅行 树形DP
- hihoCoder 1035 自驾旅行 树形dp
- hihocoder #1035 : 自驾旅行 III 树形DP
- 树形DP之自驾旅行
- hihocoder #1035 : 自驾旅行 III
- hihocoder 1243 树形DP
- Hihocoder #1479 : 三等分 树形DP
- hihocoder 1055 刷油漆(树形DP+背包)
- 树形DP--HihoCoder 1104 Suzhou Adventure
- hihocoder 1055 刷油漆(树形dp)
- hihocoder-1055 刷油漆(树形DP)
- hihocoder #1055 : 刷油漆(树形dp)
- Hihocoder 1055 树形DP(分组背包)
- BZOJ(本校) 3044 旅行 - 树形dp&基环树
- [树形DP] HihoCoder #1471 Challenge 27 拥堵的城市
- 【树dp+状态机背包】 自驾旅行III 找最小权路径
- 树形DP练习 转自ZEROCLOCK
- hihocoder 1247 树形XX~~
- VB.net之旅-SQLHelper的应用程序配置文件和使用(机房收费系统重构个人版)
- 苹果所有常用证书,appID,Provisioning Profiles配置说明及制作图文教程(精)
- 数的计数
- POJ 1458最长公共子序列(DP)
- 通过 ulimit 改善系统性能
- hihoCoder 1035 自驾旅行 树形DP
- Java集合源码学习(14)_BlockingQueue接口
- csdn夏令营week 1
- 栈的Java实现
- java的括号匹配程序
- 排序算法实现
- 步步为营(一) 知识架构和要点分析
- POJ 3624 01背包(DP)
- TFS安装使用笔记——TFS外网访问(单服务器非域安装)