POJ 2057 The Lost House 经典树形DP+贪心
来源:互联网 发布:免费cms系统哪个好 编辑:程序博客网 时间:2024/06/06 01:58
题意:链接
方法:树形DP+贪心
解析:这是一道好题。
好首先要明确这题求的是什么?
名义上是期望值,而实际上就是找一条路径。什么路径呢?从根节点走遍所有的叶子节点所花费步数最短的路径。
明确了题意后该怎么做呢?
首先看我们需要什么?
目前有个根节点,我们需要知道从他向一个分支走,失败步数是多少,成功步数是多少?
那么怎么维护我们需要的东西呢?
首先我们先给他们起个名:suc,fai;
其次再给一个节点的叶子节点的个数起个名:son
起名完事之后我们就要更新了。
先谈叶子节点,显然叶子节点的suc[x]=0,fai[x]=0,son[x]=1;
之后就是向上更新了,son和fai也很好搞
对于son的更新son[fa]+=son[x];
对于fai的更新fai[fa]+=fai[x]+2(此时worm[x]=0);否则的话不用管。
对于最不好弄的suc更新:
首先对于我们当前讨论的要走的子节点pn,这时候,蜗牛已经经过了走p1~pn-1的失败的步数,所以这些失败的步数是要记录的,我们给它命名为cnt-fai,此时我们会多走几个cnt-fai呢?我们发现,一共会多走son[pn]个cnt-fai,然而每次走过一个叶子节点后,更新一次suc[x],然后再将其视为失败,返回,找下一个叶子节点,此时我们就会发现,再返回到px的时候,这个蜗牛还需要继续返回一层,即返回到目前的根节点x,多走出一步,多走多少个一步呢?仍然是son[pn]个,用公式来写就是这样:suc[x]+=(cntfai+1)∗son[pn]+suc[pn]
同时更新cntfai,cntfai+=fai[pn]+2 这个2就是指去以及回来的两步
以上,dp的部分差不多搞定了,观察上面的式子发现,唯一不能确定的就是pn是什么鬼?
也就是说,对于一个根节点x我们按照什么顺序来讨论他的子节点会使得x的suc最小呢?
以下引用discuss里某神犇的证明
假设交换相邻的两颗子树的选择顺序,设P1,P2为选他们的概率,A1,A2为房子确实在上面所需的步数,B1,B2为实际上不在上面所需的步数,则
调整后:Delta=P1*A1+P2*(B1+A2)-P2*A2-P1*(B2+A1)=P2*B1-P1*B2
于是Delta<0 <=> B1/P1小于B2/P2
而题设情况即为Delta<0
于是应按照B/L排序 即遍历此子树所需步数/其所含叶子树
转化为公式呢?就是这个东西
(fai[u]+2)∗son[v]<(fai[v]+2)∗son[u]
其中u和v分别是两个子节点。
后记:这题是道好题,做完后能学到不少东西,值得一做,然而自己在做的时候对于这种双线的把握还不是很好,比较欠缺,什么鬼的排序根本没想到,自己对于这种难题的把握还是差很多啊!
代码:
#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#define N 1100using namespace std ;int n,cnt;bool col[N];int head[N],suc[N],fai[N],son[N];char s[5];struct node{ int to,next;}edge[N];void init(){ memset(head,-1,sizeof(head)); memset(col,0,sizeof(col)); memset(suc,0,sizeof(suc)); memset(fai,0,sizeof(fai)); memset(son,0,sizeof(son)); cnt=1;}int cmp(int u,int v){ return (fai[u]+2)*son[v]<(fai[v]+2)*son[u];}void edgeadd(int from,int to){ edge[cnt].to=to; edge[cnt].next=head[from]; head[from]=cnt++;}void dfs(int u){ if(head[u]==-1) { suc[u]=0,son[u]=1,fai[u]=0; } int tmp[N],tot=0; for(int i=head[u];i!=-1;i=edge[i].next) { int to=edge[i].to; tmp[++tot]=to; dfs(to); son[u]+=son[to]; if(!col[u])fai[u]+=fai[to]+2; } sort(tmp+1,tmp+1+tot,cmp); int cnt_fai=0; for(int i=1;i<=tot;i++) { suc[u]+=(cnt_fai+1)*son[tmp[i]]+suc[tmp[i]]; cnt_fai+=fai[tmp[i]]+2; }}int main(){ while(scanf("%d",&n)&&n!=0) { init(); for(int i=1;i<=n;i++) { int pre; scanf("%d%s",&pre,s); col[i]=s[0]=='Y'?1:0; if(pre==-1)continue; edgeadd(pre,i); } dfs(1); printf("%.4lf\n",(double)suc[1]/(double)son[1]); }}
0 0
- POJ 2057 The Lost House 经典树形DP+贪心
- POJ 2057 The Lost House 树形DP+贪心
- 【树形DP】【poj 2057】The Lost House
- The Lost House--经典树形DP
- POJ 2057 The Lost House 树状DP
- POJ 2057 The Lost House 树型dp+贪心思想在动态规划上的应用
- poj_2057 The Lost House(树形dp)
- POJ 2057 The lost house
- poj 2057 The Lost House
- POJ 2057 The Lost House
- POJ 2057 The Lost House
- POJ 2057 The Lost House
- poj-2057 The Lost House
- poj 2057 The Lost House
- pku 2057 The Lost House 树形dp+背包dp 解题报告
- 【Poj 2507】The Lost House(树型dp)
- poj 2057 树形DP+一点贪心
- 【树状数组】PKU-2057-The Lost House
- GRE写作真题——社会与自然
- 设置Launch Image 启动图片
- 浅谈文字编码和Unicode
- 计算机哲学博客
- GPU 加速下的图像视觉
- POJ 2057 The Lost House 经典树形DP+贪心
- Linux Tools Quick Tutorial
- Android ListView CheckBox状态错乱
- 连载四 奖学金文章更新 张文军 北京IOS第38期学员
- 制作旅游网站需要考虑的要素
- socket I/O模型 之 select
- android5.0版本对.so文件适配的简单测试分析
- Android webview使用详解
- 提取VS的Win32SDk用C/C++编译器