概率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抢票成功的 ...
随机推荐
- css3 一个六边形 和 放大旋转动画DEMO演示
<!DOCTYPE html> <html> <head> <meta charset="gb2312"> <title> ...
- Delphi 日期函数(Day、Mon、Year、Week)使用方法描述
Day 开头的函数 ● function DateOf(const Avalue: TDateTime): TDateTime; 描述 使用 DateOf 函数用来把一个 TDateTime 类型的变 ...
- JS分支结构与循环结构
1.分支结构 ①if语句 语法结构 if (/* 条件表达式 */) { // 执行语句 } if (/* 条件表达式 */){ // 成立执行语句 } else { // 否则执行语句 } ...
- 获取ThinkPHP
获取ThinkPHP的方式很多,官方网站(http://thinkphp.cn)是最好的下载和文档获取来源. 官网提供了稳定版本的下载:http://thinkphp.cn/down/framewor ...
- BZOJ 3779: 重组病毒(线段树+lct+树剖)
题面 escription 黑客们通过对已有的病毒反编译,将许多不同的病毒重组,并重新编译出了新型的重组病毒.这种病毒的繁殖和变异能力极强.为了阻止这种病毒传播,某安全机构策划了一次实验,来研究这种病 ...
- (转)Java NIO框架Mina、Netty、Grizzly介绍与对比
转:http://blog.csdn.net/cankykong1/article/details/19937027 Mina: Mina(Multipurpose Infrastructure fo ...
- fasttext源码剖析
fasttext源码剖析 目的:记录结合多方资料以及个人理解的剖析代码: https://heleifz.github.io/14732610572844.html http://www.cnbl ...
- Java-Class-@I:org.springframework.stereotype.Service
ylbtech-Java-Class-@I:org.springframework.stereotype.Service 1.返回顶部 2.返回顶部 1. package com.ylbtech. ...
- iOS开发inputView和inputAccessoryView
1.简介 起初看到这两个属性是在UIResponder中,只是可读的: @property (nullable, nonatomic, readonly, strong) __kindof UIVie ...
- Java 核心编程技术干货,2019 最新整理版!
Java技术栈 www.javastack.cn 优秀的Java技术公众号 以下是Java技术栈微信公众号发布的所有关于 Java 的技术干货,会从以下几个方面汇总,本文会长期更新. Java 基础篇 ...