http://acm.hdu.edu.cn/showproblem.php?pid=4035

获得:

1、首先推断是不是树。事实上,所有的感觉身影,既看边数==算-1是不成立

2、有时候,我告诉孩子来区分树仍然是必要的,就是,只是是在dfs的时候,传參数的时候多加个表示父节点的參数而已

3、一定注意,概率DP对精度真的要求非常高 開始的时候写1e-8,WA了好几发,改了1e-10  AC

4、注意分母为0的可能的时候加上推断

讲的非常具体的题解:http://blog.csdn.net/morgan_xww/article/details/6776947

直接按公式写的代码就是:

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <string>
#include <iostream>
#include <iomanip>
#include <cmath>
#include <map>
#include <set>
#include <queue>
using namespace std; #define ls(rt) rt*2
#define rs(rt) rt*2+1
#define ll long long
#define ull unsigned long long
#define rep(i,s,e) for(int i=s;i<e;i++)
#define repe(i,s,e) for(int i=s;i<=e;i++)
#define CL(a,b) memset(a,b,sizeof(a))
#define IN(s) freopen(s,"r",stdin)
#define OUT(s) freopen(s,"w",stdout)
const ll ll_INF = ((ull)(-1))>>1;
const double EPS = 1e-10;
const int INF = 100000000;
const int MAXN = 10000+100; vector<int>g[MAXN];
double k[MAXN],e[MAXN];
double a[MAXN],b[MAXN],c[MAXN];
int n; bool sea(int i, int fa)
{
if(g[i].size() == 1 && fa!=-1)//叶子节点
{
a[i]=k[i];
c[i]=b[i]=1.0-k[i]-e[i];
return true;
}
//非叶子节点,此时该非叶子节点的子孙都已经遍历过了
double aa=0.0,bb=0.0,cc=0.0;
for(int j=0;j<g[i].size();j++)
{
if( g[i][j] == fa)continue;
if(!sea(g[i][j],i))return 0;
aa+=a[g[i][j]];
bb+=b[g[i][j]];
cc+=c[g[i][j]];
}
int m=g[i].size();
a[i]=(k[i]+(1-k[i]-e[i])/m*aa)/(1-(1.0-k[i]-e[i])/m*bb);
b[i]=(1.0-k[i]-e[i])/m/(1.0-(1.0-k[i]-e[i])/m*bb);
c[i]=( (1.0-k[i]-e[i])+(1.0-k[i]-e[i])/m*cc )/(1.0 -(1.0-k[i]-e[i])/m*bb);
return true;
} int main()
{
int ncase,u,v,ic=0; scanf("%d",&ncase);
while(ncase--)
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
g[i].clear();
for(int i=1;i<n;i++)
{
scanf("%d%d",&u,&v);
g[u].push_back(v);
g[v].push_back(u);
}
for(int i=1;i<=n;i++)
{
scanf("%lf%lf",&k[i],&e[i]);
k[i]/=100.0;
e[i]/=100.0;
} printf("Case %d: ",++ic);
if(sea(1,-1) && fabs(1.0-a[1])>EPS)
printf("%.6lf\n",c[1]/(1.0-a[1]));
else
printf("impossible\n");
}
return 0;
}

当然更好的写法还是题解上的

#include <cstdio>
#include <iostream>
#include <vector>
#include <cmath> using namespace std; const int MAXN = 10000 + 5; double e[MAXN], k[MAXN];
double A[MAXN], B[MAXN], C[MAXN]; vector<int> v[MAXN]; bool search(int i, int fa)
{
if ( v[i].size() == 1 && fa != -1 )
{
A[i] = k[i];
B[i] = 1 - k[i] - e[i];
C[i] = 1 - k[i] - e[i];
return true;
} A[i] = k[i];
B[i] = (1 - k[i] - e[i]) / v[i].size();
C[i] = 1 - k[i] - e[i];
double tmp = 0; for (int j = 0; j < (int)v[i].size(); j++)
{
if ( v[i][j] == fa ) continue;
if ( !search(v[i][j], i) ) return false;
A[i] += A[v[i][j]] * B[i];
C[i] += C[v[i][j]] * B[i];
tmp += B[v[i][j]] * B[i];
}
if ( fabs(tmp - 1) < 1e-10 ) return false;
A[i] /= 1 - tmp;
B[i] /= 1 - tmp;
C[i] /= 1 - tmp;
return true;
} int main()
{
int nc, n, s, t; cin >> nc;
for (int ca = 1; ca <= nc; ca++)
{
cin >> n;
for (int i = 1; i <= n; i++)
v[i].clear(); for (int i = 1; i < n; i++)
{
cin >> s >> t;
v[s].push_back(t);
v[t].push_back(s);
}
for (int i = 1; i <= n; i++)
{
cin >> k[i] >> e[i];
k[i] /= 100.0;
e[i] /= 100.0;
} cout << "Case " << ca << ": ";
if ( search(1, -1) && fabs(1 - A[1]) > 1e-10 )
cout << C[1]/(1 - A[1]) << endl;
else
cout << "impossible" << endl;
}
return 0;
}

版权声明:本文博客原创文章,博客,未经同意,不得转载。

hdu 4035 可能性DP 成都网络游戏的更多相关文章

  1. poj 2096 , zoj 3329 , hdu 4035 —— 期望DP

    题目:http://poj.org/problem?id=2096 题目好长...意思就是每次出现 x 和 y,问期望几次 x 集齐 n 种,y 集齐 s 种: 所以设 f[i][j] 表示已经有几种 ...

  2. HDU 4035 期望dp

    这道题站在每个位置上都会有三种状态 死亡回到起点:k[i] 找到出口结束 e[i] 原地不动 p[i] k[i]+e[i]+p[i] =1; 因为只给了n-1条路把所有都连接在一起,那么我们可以自然的 ...

  3. hdu 4035 2011成都赛区网络赛E 概率dp ****

    太吊了,反正我不会 /* HDU 4035 dp求期望的题. 题意: 有n个房间,由n-1条隧道连通起来,实际上就形成了一棵树, 从结点1出发,开始走,在每个结点i都有3种可能: 1.被杀死,回到结点 ...

  4. poj 2096 Collecting Bugs && ZOJ 3329 One Person Game && hdu 4035 Maze——期望DP

    poj 2096 题目:http://poj.org/problem?id=2096 f[ i ][ j ] 表示收集了 i 个 n 的那个. j 个 s 的那个的期望步数. #include< ...

  5. [AC自己主动机+可能性dp] hdu 3689 Infinite monkey theorem

    意甲冠军: 给n快报,和m频率. 然后进入n字母出现的概率 然后给目标字符串str 然后问m概率倍的目标字符串是敲数量. 思维: AC自己主动机+可能性dp简单的问题. 首先建立trie图,然后就是状 ...

  6. hdu 4123 树形DP+RMQ

    http://acm.hdu.edu.cn/showproblem.php? pid=4123 Problem Description Bob wants to hold a race to enco ...

  7. hdu 4507 数位dp(求和,求平方和)

    http://acm.hdu.edu.cn/showproblem.php?pid=4507 Problem Description 单身! 依旧单身! 吉哥依旧单身! DS级码农吉哥依旧单身! 所以 ...

  8. hdu 3709 数字dp(小思)

    http://acm.hdu.edu.cn/showproblem.php?pid=3709 Problem Description A balanced number is a non-negati ...

  9. hdu 4352 数位dp + 状态压缩

    XHXJ's LIS Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total ...

随机推荐

  1. Android 利用线程运行栈StackTraceElement设计Android日志模块

    如果你想在你的Android程序中自动打印MainActivity.onCreate(line:37)这种类名.方法名(行数)的日志该如何实现呢? 1.引入Java的线程运行栈 Java.lang包中 ...

  2. TortoiseGit拉取或推送项目提示 HTTP Basic: Access denied fatal: Authentication failed.

      TortoiseGit拉取或推送项目提示 HTTP Basic: Access denied fatal: Authentication failed. 大体意思是,HTTP基本认证失败,访问被拒 ...

  3. 【34.88%】【codeforces 569C】Primes or Palindromes?

    time limit per test3 seconds memory limit per test256 megabytes inputstandard input outputstandard o ...

  4. Java NIO的基本概念与使用

    public class TestBuffer { /** * 一. 缓冲区 (Buffer):Java Nio中负责数据的 存取+缓冲就是数组.用于存储不同类型的数据 * * 根据类型不同(bool ...

  5. java生成6位随机数

    生成6位随机数(不会是5位或者7位,仅只有6位): System.out.println((int)((Math.random()*9+1)*100000)); 同理,生成5位随机数: System. ...

  6. 原生js如何实现图片翻转旋转效果?

    原生js如何实现图片翻转旋转效果? 一.总结 1.通过给元素设置style中的transition来实现的. 2.我昨天纠结的效果全部可以通过精读这个代码后实现. 二.原生js如何实现图片翻转旋转效果 ...

  7. Android 自动弹出软键盘(输入键盘)

    很多应用中对于一个界面比如进入搜索界面或者修改信息等等情况,为了用户体验应该自动弹出软键盘而不是让用户主动点击输入框才弹出(因为用户进入该界面必然是为了更改信息).具体实现这种效果如下: EditTe ...

  8. 【U205】最大值

    Time Limit: 1 second Memory Limit: 128 MB [问题描述] 找到一个数组的最大值的一种方法是从数组开头从前到后对数组进行扫描,令max=a[0](数组下表从0.. ...

  9. JSON 表达式

    JSON语法规则:     数据在名称/值对中:     数据由逗号分隔:     大括号保存对象:     中括号保存数组 1.访问对象值: var myObj,x; myObj = {" ...

  10. SQL中where语句不能使用直接跟在select后列的别名

    由于select语句的执行顺序为: 1. from语句 2. where语句(结合条件) 3. start with语句 4. connect by语句 5. where语句 6. group by语 ...