Hdu 4219 Randomization?【树型Dp】好题~但是好难呀.

224 篇文章 2 订阅

Randomization?

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 297    Accepted Submission(s): 171


Problem Description
Random is the real life. What we see and sense everyday are absolutely randomly happened. Randomization is the process of making something random, as the nature.
Given a tree with N nodes, to be more precisely, a tree is a graph in which each pair of nodes has and only has one path. All of the edges’ length is a random integer lies in interval [0, L] with equal probability. iSea want to know the probability to form a tree, whose edges’ length are randomly generated in the given interval, and in which the path's length of every two nodes does not exceed S.
 

Input
The first line contains a single integer T, indicating the number of test cases.
Each test case includes three integers N, L, S. Then N - 1 lines following, each line contains two integers Ai and Bi, describing an edge of the tree.

Technical Specification
1. 1 <= T <= 512
2. 1 <= N <= 64
3. 1 <= L <= 8, 1 <= S <= 512
4. 1 <= Ai, Bi <= N
 

Output
For each test case, output the case number first, then the probability rounded to six fractional digits.
 

Sample Input
  
  
3 2 3 2 1 2 4 3 4 1 2 2 3 3 4 7 4 10 1 2 2 3 4 5 2 6 4 7 4 6
 

Sample Output
  
  
Case 1: 0.750000 Case 2: 0.500000 Case 3: 0.624832
 

Author
iSea@WHU
 

Source

树型Dp都好难呀、


题目大意:


给你N个点构成的一棵树。每条边的权值可以设定为【0,L】区间内的任意一个价值,问任意两点间距离都不超过S的设定方案的概率。


思路:


思路参考自网络代码,看懂好难呀。


①设定Dp【u】【len】表示从节点u到以节点u为根的子树中的所有点的最大距离是len的概率,并且需要奥正其子树节点中两两距离不超过S。


②那么考虑两两子节点进行合并(哇第一次见这种骚操作。)


③设定Dist【i】表示当前子节点v的子树中,距离节点u的最远距离为i的概率。

那么有:Dist【k+j】+=dp【v】【k】*(1/(L+1))这里j是枚举的从节点v到节点u这条路径上的长度。


④再设定temp【i】表示合并完当前节点v之后的dp【u】【i】的答案。

那么有:temp【max(j,k)】+=dp【u】【k】*Dist【j】;这里需要同时保证j+k<=S;

接下来每次合并结束之后,将dp【u】【i】更新为temp【i】,然后考虑合并下一个子节点v.


Ac代码:

#include<stdio.h>
#include<string.h>
#include<vector>
using namespace std;
vector<int>mp[150];
double dp[65][515];
int n,L,S;
double mm;
double Dist[525];
double temp[525];
void Dfs(int u,int from)
{
    mm=1;
    mm/=(double)(L+1);
    for(int i=0; i<=S; i++)dp[u][i]=0;
    dp[u][0]=1;
    for(int i=0;i<mp[u].size();i++)
    {
        int v=mp[u][i];
        if(v==from)continue;
        else
        {
            Dfs(v,u);
            for(int j=0;j<=S;j++)
            {
                Dist[j]=temp[j]=0;
            }
            for(int j=0;j<=L;j++)
            {
                for(int k=0;k<=S;k++)
                {
                    if(j+k<=S)
                    Dist[j+k]+=mm*dp[v][k];
                }
            }
            for(int j=0;j<=S;j++)
            {
                for(int k=0;k<=S-j;k++)
                {
                    temp[max(j,k)]+=dp[u][k]*Dist[j];
                }
            }
            for(int j=0;j<=S;j++)dp[u][j]=temp[j];
        }
    }
}
int main()
{
    int t;
    int kase=0;
    scanf("%d",&t);
    while(t--)
    {
        memset(dp,0,sizeof(dp));
        scanf("%d%d%d",&n,&L,&S);
        for(int i=1; i<=n; i++)mp[i].clear();
        for(int i=0; i<n-1; i++)
        {
            int x,y;
            scanf("%d%d",&x,&y);
            mp[x].push_back(y);
            mp[y].push_back(x);
        }
        Dfs(1,-1);
        double output=0;
        for(int i=0; i<=S; i++)
        {
            output+=dp[1][i];
        }
        printf("Case %d: %.6f\n",++kase,output);
    }
}








  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值