学习资料
- 百度百科 - 期望
- 浅谈概率期望 By 朝阳的二愣子
- 概率DP/期望DP总结 By myjs999
- 动态规划 —— 概率 DP 与期望 DP By Alex_McAvoy
- 【概率期望动态规划】 By 大米饼
- 【整理】简单的数学期望和概率DP By nimphy
练习题
luogu 1850 NOIP2016 换教室
传送门:luogu1850
我的题解:luogu1850 换教室
/*************************
User:Mandy.H.Y
Language:c++
Problem:luogu1850
Algorithm:
*************************/
#include<bits/stdc++.h>
using namespace std;
const int maxn = 2005;
const int maxv = 305;
const int maxe = 90005;
int n,m,v,e,size;
int c[maxn],d[maxn];
double k[maxn],dp[maxn][maxn][3];
int g[maxv][maxv];
struct Edge{
int v,nt,w;
}edge[maxe << 1];
template<class T>inline void read(T &x){
x = 0;bool flag = 0;char ch = getchar();
while(!isdigit(ch)) flag |= ch == '-',ch = getchar();
while(isdigit(ch)) x = (x << 1) + (x << 3) + (ch ^ 48),ch = getchar();
if(flag) x = -x;
}
template<class T>void putch(const T x){
if(x > 9) putch(x / 10);
putchar(x % 10 | 48);
}
template<class T>void put(const T x){
if(x < 0) putchar('-'),putch(-x);
else putch(x);
}
void file(){
freopen("1850.in","r",stdin);
freopen("1850.out","w",stdout);
}
void readdata(){
memset(g,0x3f3f3f3f,sizeof(g));
read(n);read(m);read(v);read(e);
for(int i = 1;i <= v; ++ i) g[i][i] = 0;
for(int i = 1;i <= n; ++ i) read(c[i]);
for(int i = 1;i <= n; ++ i) read(d[i]);
for(int i = 1;i <= n; ++ i) scanf("%lf",&k[i]);
for(int i = 1;i <= e; ++ i) {
int u,v,w;
read(u);read(v);read(w);
g[u][v] = min(g[u][v],w);
g[v][u] = g[u][v];
}
}
void Floyd(){
for(int l = 1;l <= v; ++ l)
for(int i = 1;i <= v; ++ i)
for(int j = 1;j <= v; ++ j){
if(g[i][l] != 0x3f3f3f3f && g[l][j] != 0x3f3f3f3f)
if(g[i][l] + g[l][j] < g[i][j]) g[i][j] = g[i][l] + g[l][j];
}
}
void work(){
Floyd();
for(int i = 2;i <= n; ++ i){
int u1 = c[i - 1],u2 = d[i - 1];
int v1 = c[i],v2 = d[i];
dp[i][0][0] = dp[i - 1][0][0] + g[u1][v1];
for(int j = 1;j <= m; ++ j){
dp[i][j][0] = min(dp[i - 1][j][0] + g[u1][v1],
dp[i - 1][j][1] +
k[i - 1] * g[u2][v1] +
(1 - k[i - 1]) * g[u1][v1]);
dp[i][j][1] = dp[i - 1][j - 1][0] +
k[i] * g[u1][v2] +
(1 - k[i]) * g[u1][v1];
if(j > 1) dp[i][j][1] = min(dp[i][j][1],dp[i - 1][j - 1][1] +
k[i - 1] * k[i] * g[u2][v2] +
k[i - 1] * (1 - k[i]) * g[u2][v1] +
(1 - k[i - 1]) * k[i] * g[u1][v2] +
(1 - k[i - 1]) * (1 - k[i]) * g[u1][v1]);
}
}
double ans = 2000000000.0;
for(int i = 0;i <= m; ++ i) {
ans = min(ans,dp[n][i][0]);
if(i > 0) ans = min(ans,dp[n][i][1]);
}
printf("%.2lf",ans);
}
int main(){
// file();
readdata();
work();
return 0;
}
HDU4576 Robot
传送门:hdu4576
Problem Description
Michael has a telecontrol robot. One day he put the robot on a loop with n cells. The cells are numbered from 1 to n clockwise.
At first the robot is in cell 1. Then Michael uses a remote control to send m commands to the robot. A command will make the robot walk some distance. Unfortunately the direction part on the remote control is broken, so for every command the robot will chose a direction(clockwise or anticlockwise) randomly with equal possibility, and then walk w cells forward.
Michael wants to know the possibility of the robot stopping in the cell that cell number >= l and <= r after m commands.
Input
There are multiple test cases.
Each test case contains several lines.
The first line contains four integers: above mentioned n(1≤n≤200) ,m(0≤m≤1,000,000),l,r(1≤l≤r≤n).
Then m lines follow, each representing a command. A command is a integer w(1≤w≤100) representing the cell length the robot will walk for this command.
The input end with n=0,m=0,l=0,r=0. You should not process this test case.
Output
For each test case in the input, you should output a line with the expected possibility. Output should be round to 4 digits after decimal points.
Sample Input
3 1 1 2
1
5 2 4 4
1
2
0 0 0 0
Sample Output
0.5000
0.2500
翻译及题解:hdu 4576 Robot
/***********************
User:Mandy.H.Y
Language:c++
Problem:hdu4576
Algorithm:
************************/
//一个概率 + 环形的背包?
#include<cstdio>
#include<cmath>
#include<iomanip>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn = 205;
const int maxm = 1e6 + 5;
int n,m,l,r;
double f[2][maxn],ans = 0;
template<class T>inline void read(T &x){
x = 0;bool flag = 0;char ch = getchar();
while(!isdigit(ch)) flag |= ch == '-',ch = getchar();
while(isdigit(ch)) x = (x << 1) + (x << 3) + (ch ^ 48),ch = getchar();
if(flag) x = -x;
}
template<class T>void putch(const T x){
if(x > 9) putch(x / 10);
putchar(x % 10 | 48);
}
template<class T>void put(const T x){
if(x < 0) putchar('-'),putch(-x);
else putch(x);
}
void file(){
freopen("4576.in","r",stdin);
freopen("4576.out","w",stdout);
}
int get(int x){
if(x < 1) return x + n;
if(x > n) return x - n;
return x;
}
void work(){
memset(f,0,sizeof(f));//记得清零
f[0][1] = 1;
int cur = 1;ans = 0;
for(int i = 1;i <= m; ++ i) {
int w;read(w);w %= n;//要对n取模,防止溢出
for(int i = 1;i <= n; ++ i){
f[cur][i] = f[cur ^ 1][get(i - w)] * 0.5;
f[cur][i] += f[cur ^ 1][get(i + w)] * 0.5;
}
cur ^= 1;
}
cur ^= 1;
for(int i = l;i <= r; ++ i) ans += f[cur][i];
}
int main(){
// file();
while(scanf("%d%d%d%d",&n,&m,&l,&r)){
if((!n) && (!m) && (!l) && (!r)) break;
work();
printf("%.4lf\n",ans);
}
return 0;
}
MZOJ #78 小象涂色
题目及分析:MZOJ #78 小象涂色
/**************************
User:Mandy.H.Y
Language:c++
Problem:elephant
Algorithm:
**************************/
#include<bits/stdc++.h>
using namespace std;
const int maxn = 55;
int t,n,c,k;
int sum[maxn];
double cur[maxn][105];
double b[105];
char *TT,*mo,but[(1 << 15) + 2];
#define getchar() ((TT == mo && (mo = ((TT = but) + fread(but,1,1 << 15,stdin)), TT == mo)) ? -1 : *TT++)
template<class T>inline void read(T &x){
x = 0;bool flag = 0;char ch = getchar();
while(!isdigit(ch)) flag |= ch == '-',ch = getchar();
while(isdigit(ch)) x = (x << 1) + (x << 3) + (ch ^ 48),ch = getchar();
if(flag) x = -x;
}
template<class T>void putch(const T x){
if(x > 9) putch(x / 10);
putchar(x % 10 | 48);
}
template<class T>void put(const T x){
if(x < 0) putchar('-'),putch(-x);
else putch(x);
}
void file(){
freopen("elephant.in","r",stdin);
freopen("elephant.out","w",stdout);
}
void readdata(){
read(n);read(c);read(k);
memset(sum,0,sizeof(sum));
memset(cur,0,sizeof(cur));
memset(b,0,sizeof(b));
}
void work(){
readdata();
double color = ((double)1.0 / (double)c);
for(int z = 1;z <= k; ++ z){
int l,r;
read(l);read(r);
sum[l]++;
sum[r+1]--;
}
for(int i = 1;i <= n; ++ i) sum[i] += sum[i-1];
cur[0][1] = 1;//初始都是颜色1
for(int i = 1;i <= k; ++ i){
for(int j = 0;j < c; ++ j){
cur[i][j] = cur[i - 1][j] * 0.5;
}
for(int j = 0;j < c; ++ j){
for(int x = 0;x < c; ++ x){
cur[i][j * x % c] += cur[i-1][j] * 0.5 * color;
}
}
}
double ans = 0;
for(int i = 1;i <= n; ++ i){
for(int j = 0;j < c; ++ j){
ans += cur[sum[i]][j] * j;
}
}
printf("%.9lf\n",ans);
}
int main(){
// file();
read(t);
while(t --)
work();
return 0;
}