概率dp的迭代方式小结——zoj3329,hdu4089,hdu4035
在推导期望方程时我们常常会遇到dp[i]和其他项有关联,那么这时候我们就难以按某个顺序进行递推
即难以通过已经确定的项来求出新的项
即未知数的相互关系是循环的
但是我们又可以确定和dp[i]相关联的项是有规律的,即存在一个可以递推dp[i]的通项公式,那么不妨设置未知数,通过原方程的迭代来打破这种循环
为了完成递推,我们需要通过递推和dp[i]有关的参数来间接求出dp[i]
比如递推方程dp[i]总是和dp[1]有关,那么我们可以肯定dp[i]=ai*dp[1]+b[i]
那么用这个方程进行迭代,最后可以发现ai是能够逆着递推的
zoj3329:dp[i]=a[i]dp[0]+b[i]
这题dp[i]总是和dp[0]有关,假设dp[i+k]的值都知道了(等价于常数b[i]),那么a[i]就是个可以递推的项
hdu:dp[i][j]=a[j]*dp[i][i]+c[j]
hdu4035:树上迭代,因为正常的顺序是从叶子推导到根,但是每个结点会受到dp[rt]和dp[fa]的影响, 所以这两项要用两个参数来迭代
dp[u]=a[u]*dp[rt]+b[u]*dp[fa]+c[u]
#include <cstdio>
#include <iostream>
#include <vector>
#include <cmath> using namespace std; const int MAXN = + ; 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() == && fa != - )
{
A[i] = k[i];
B[i] = - k[i] - e[i];
C[i] = - k[i] - e[i];
return true;
} A[i] = k[i];
B[i] = ( - k[i] - e[i]) / v[i].size();
C[i] = - k[i] - e[i];
double tmp = ; for (int j = ; 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 - ) < 1e- ) return false;
A[i] /= - tmp;
B[i] /= - tmp;
C[i] /= - tmp;
return true;
} int main()
{
int nc, n, s, t; cin >> nc;
for (int ca = ; ca <= nc; ca++)
{
scanf("%d",&n);
for (int i = ; i <= n; i++)
v[i].clear(); for (int i = ; i < n; i++)
{
scanf("%d%d",&s,&t);
v[s].push_back(t);
v[t].push_back(s);
}
for (int i = ; i <= n; i++)
{
scanf("%lf%lf",&k[i],&e[i]);
k[i] /= 100.0;
e[i] /= 100.0;
} cout << "Case " << ca << ": ";
if ( search(, -) && fabs( - A[]) > 1e- )
cout << C[]/( - A[]) << endl;
else
cout << "impossible" << endl;
}
return ;
}
#include <cstdio>
#include <iostream>
#include <vector>
#include <cmath> using namespace std; const int MAXN = + ; 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() == && fa != - )
{
A[i] = k[i];
B[i] = - k[i] - e[i];
C[i] = - k[i] - e[i];
return true;
} A[i] = k[i];
B[i] = ( - k[i] - e[i]) / v[i].size();
C[i] = - k[i] - e[i];
double tmp = ; for (int j = ; 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 - ) < 1e- ) return false;
A[i] /= - tmp;
B[i] /= - tmp;
C[i] /= - tmp;
return true;
} int main()
{
int nc, n, s, t; cin >> nc;
for (int ca = ; ca <= nc; ca++)
{
scanf("%d",&n);
for (int i = ; i <= n; i++)
v[i].clear(); for (int i = ; i < n; i++)
{
scanf("%d%d",&s,&t);
v[s].push_back(t);
v[t].push_back(s);
}
for (int i = ; i <= n; i++)
{
scanf("%lf%lf",&k[i],&e[i]);
k[i] /= 100.0;
e[i] /= 100.0;
} cout << "Case " << ca << ": ";
if ( search(, -) && fabs( - A[]) > 1e- )
cout << C[]/( - A[]) << endl;
else
cout << "impossible" << endl;
}
return ;
}
#include <cstdio>
#include <iostream>
#include <vector>
#include <cmath> using namespace std; const int MAXN = + ; 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() == && fa != - )
{
A[i] = k[i];
B[i] = - k[i] - e[i];
C[i] = - k[i] - e[i];
return true;
} A[i] = k[i];
B[i] = ( - k[i] - e[i]) / v[i].size();
C[i] = - k[i] - e[i];
double tmp = ; for (int j = ; 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 - ) < 1e- ) return false;
A[i] /= - tmp;
B[i] /= - tmp;
C[i] /= - tmp;
return true;
} int main()
{
int nc, n, s, t; cin >> nc;
for (int ca = ; ca <= nc; ca++)
{
scanf("%d",&n);
for (int i = ; i <= n; i++)
v[i].clear(); for (int i = ; i < n; i++)
{
scanf("%d%d",&s,&t);
v[s].push_back(t);
v[t].push_back(s);
}
for (int i = ; i <= n; i++)
{
scanf("%lf%lf",&k[i],&e[i]);
k[i] /= 100.0;
e[i] /= 100.0;
} cout << "Case " << ca << ": ";
if ( search(, -) && fabs( - A[]) > 1e- )
cout << C[]/( - A[]) << endl;
else
cout << "impossible" << endl;
}
return ;
}
#include <cstdio>
#include <iostream>
#include <vector>
#include <cmath> using namespace std; const int MAXN = + ; 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() == && fa != - )
{
A[i] = k[i];
B[i] = - k[i] - e[i];
C[i] = - k[i] - e[i];
return true;
} A[i] = k[i];
B[i] = ( - k[i] - e[i]) / v[i].size();
C[i] = - k[i] - e[i];
double tmp = ; for (int j = ; 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 - ) < 1e- ) return false;
A[i] /= - tmp;
B[i] /= - tmp;
C[i] /= - tmp;
return true;
} int main()
{
int nc, n, s, t; cin >> nc;
for (int ca = ; ca <= nc; ca++)
{
scanf("%d",&n);
for (int i = ; i <= n; i++)
v[i].clear(); for (int i = ; i < n; i++)
{
scanf("%d%d",&s,&t);
v[s].push_back(t);
v[t].push_back(s);
}
for (int i = ; i <= n; i++)
{
scanf("%lf%lf",&k[i],&e[i]);
k[i] /= 100.0;
e[i] /= 100.0;
} cout << "Case " << ca << ": ";
if ( search(, -) && fabs( - A[]) > 1e- )
cout << C[]/( - A[]) << endl;
else
cout << "impossible" << endl;
}
return ;
}
#include <cstdio>
#include <iostream>
#include <vector>
#include <cmath> using namespace std; const int MAXN = + ; 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() == && fa != - )
{
A[i] = k[i];
B[i] = - k[i] - e[i];
C[i] = - k[i] - e[i];
return true;
} A[i] = k[i];
B[i] = ( - k[i] - e[i]) / v[i].size();
C[i] = - k[i] - e[i];
double tmp = ; for (int j = ; 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 - ) < 1e- ) return false;
A[i] /= - tmp;
B[i] /= - tmp;
C[i] /= - tmp;
return true;
} int main()
{
int nc, n, s, t; cin >> nc;
for (int ca = ; ca <= nc; ca++)
{
scanf("%d",&n);
for (int i = ; i <= n; i++)
v[i].clear(); for (int i = ; i < n; i++)
{
scanf("%d%d",&s,&t);
v[s].push_back(t);
v[t].push_back(s);
}
for (int i = ; i <= n; i++)
{
scanf("%lf%lf",&k[i],&e[i]);
k[i] /= 100.0;
e[i] /= 100.0;
} cout << "Case " << ca << ": ";
if ( search(, -) && fabs( - A[]) > 1e- )
cout << C[]/( - A[]) << endl;
else
cout << "impossible" << endl;
}
return ;
}
概率dp的迭代方式小结——zoj3329,hdu4089,hdu4035的更多相关文章
- ZOJ 3329-One Person Game(概率dp,迭代处理环)
题意: 三个色子有k1,2,k3个面每面标号(1-k1,1-k2,1-k3),一次抛三个色子,得正面向上的三个编号,若这三个标号和给定的三个编号a1,b1,c1对应则总和置零,否则总和加上三个色子标号 ...
- ZOJ3329之经典概率DP
One Person Game Time Limit: 1 Second Memory Limit: 32768 KB Special Judge There is a very ...
- 概率dp小结
好久之前学过,记得是一次亚洲区的前几天看了看概率dp,然后亚洲区就出了一道概率dp,当时虽然做上了,但是感觉有很多地方没懂,今天起早温习了一下,觉得很多地方茅塞顿开,果然学习的话早上效果最好了. 首先 ...
- HDU4089/Uva1498 Activation 概率DP(好题)
题意:Tomato要在服务器上激活一个游戏,一开始服务器序列中有N个人,他排在第M位,每次服务器会对序列中第一位的玩家进行激活,有四种结果: 1.有p1的概率会激活失败,这时候序列的状态是不变的.2. ...
- [HDU 4089]Activation[概率DP]
题意: 有n个人排队等着在官网上激活游戏.Tomato排在第m个. 对于队列中的第一个人.有以下情况: 1.激活失败,留在队列中等待下一次激活(概率为p1) 2.失去连接,出队列,然后排在队列的最后( ...
- 动态规划之经典数学期望和概率DP
起因:在一场训练赛上.有这么一题没做出来. 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6829 题目大意:有三个人,他们分别有\(X,Y,Z\)块钱 ...
- HDU 4576 Robot(概率dp)
题目 /*********************复制来的大致题意********************** 有N个数字,M个操作, 区间L, R. 然后问经过M个操作后落在[L, R]的概率. * ...
- HDU 4089 Activation(概率DP)(转)
11年北京现场赛的题目.概率DP. 公式化简起来比较困难....而且就算结果做出来了,没有考虑特殊情况照样会WA到死的.... 去参加区域赛一定要考虑到各种情况. 像概率dp,公式推出来就很容易写 ...
- UVALive 6672 Bonus Cards 概率dp
题意呢 就是有两种售票方式 一种是icpc 一种是其他方式 icpc抢票成功的概率是其他方式的2倍…… 这时 一个人出现了 他通过内幕知道了两种抢票方式各有多少人 他想知道自己如果用icpc抢票成功的 ...
随机推荐
- vacuumdb - 收集垃圾并且分析一个PostgreSQL 数据库
SYNOPSIS vacuumdb [ connection-option...] [ --full | -f ] [ --verbose | -v ] [ --analyze | -z ] [ -- ...
- 目录文件的操作函数 mkdir ,opendir,readdir,closedir
1. int mkdir(const char *pathname, mode_t mode); 头文件 :<sys/stat.h> <sys/types.h> 功能: ...
- mount 挂载
mount 挂载出现 这是咋回事.找了找度娘,说是磁盘没有格式化.好吧,mkfs ext4 /dev/sda4 ,提示 没有有效的快给格式化,好奇怪啊,昨天明明分号区了,我记错了. fdisk看一下, ...
- easyui datagrid 绑定从后台得到的复杂的特殊数据结构
由于项目需要,从后台得到的数据统一为了类似{state:xxx,data:xxx,message:xxx}类型 但是easyui datagrid却只认{total:xxx,rows:xxx}...所 ...
- zmq的send
int zmq_send (void *socket, zmq_msg_t *msg, int flags); 2.2.1 nt zmq_send (void *socket, void * ...
- ps去除元素的三种常用方法
1.仿制图章工具,alt+鼠标左键进行选取复制区域,然后左键点击需要覆盖的区域. 2.套锁工具--选择区域--右键填充--内容识别. 3.修补工具,选中区域--拖动适配. 附带另一份较 ...
- 【Codeforces Round #589 (Div. 2) D】Complete Tripartite
[链接] 我是链接,点我呀:) [题意] 题意 [题解] 其实这道题感觉有点狗. 思路大概是这样 先让所有的点都在1集合中. 然后随便选一个点x,访问它的出度y 显然tag[y]=2 因为和他相连了嘛 ...
- 再学 GDI+文本输出文本样式
代码文件: unit Unit1; interfaceuses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls ...
- GDI+在Delphi程序的应用 Photoshop色相饱和度明度功能
本文用GDI+实现Photoshop色相/饱和度/明度功能,参照我的其它有关GDI+在 Delphi程序的应用的文章,代码也可供TBitmap使用. 有些人不喜欢,或者不太懂Delphi的BASM代码 ...
- NX二次开发-UFUN创建表达式UF_MODL_create_exp_tag有TAG
NX9+VS2012 #include <uf.h> #include <uf_modl.h> UF_initialize(); //创建一个新的表达式,无TAG UF_MOD ...