假设交换相邻的两颗子树的选择顺序,设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排序 即遍历此子树所需步数/其所含叶子树
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define N 1100
using 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]);
}
}
POJ 2057 The Lost House 经典树形DP+贪心
原文地址:http://blog.csdn.net/wzq_qwq/article/details/46359905