poj 炸了….过个把星期才能好…先刷一下HDU上的题
期望dp
这一类题,简单的说就是求期望。
一般都是从后往前推,因为最后的状态和值我们知道…
通过例题来了解~
LOOPS HDU - 3853
题意:求从(1,1)走到(r,c)的期望,每个位置有三个选择,原地不动,向右走,向下走,概率分别是(c1,c2,c3)。
分析:
dp[r][c]=0;
dp[i][j]=c1*dp[i][j]+c2*dp[i][j+1]+c3*dp[i+1][j]
递推是由已知推未知,右边的dp[i][j]未知,转移到左边
dp[i][j]=(c2*dp[i][j+1]+c3*dp[i+1][j])/(1-c1);
然后从后往前推就行了,这里注意分母不能是0,特判一下1-c1为0的情况
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <cstdio>
using namespace std;
#define ll long long
#define mem(a,b) memset(a,b,sizeof(a))
const int maxn = 1e3+10;
double c1[maxn][maxn],c2[maxn][maxn],c3[maxn][maxn],dp[maxn][maxn];
int main()
{
int r,c;
while(scanf("%d %d",&r,&c)!=EOF)
{
for(int i=1;i<=r;i++)
for(int j=1;j<=c;j++)
scanf("%lf %lf %lf",&c1[i][j],&c2[i][j],&c3[i][j]);
for(int i=0;i<=1000;i++)
for(int j=0;j<=1000;j++) dp[i][j]=0;
for(int i=r;i>=1;i--)
for(int j=c;j>=1;j--){
if(i==r&&j==c) continue;
if(abs(1.0-c1[i][j])<=1e-3) {dp[i][j]=2;continue;}
dp[i][j]=(c2[i][j]*dp[i][j+1]+c3[i][j]*dp[i+1][j]+2)/(1.0-c1[i][j]);
}
printf("%.3f\n",dp[1][1]);
}
return 0;
}
Aeroplane chess HDU - 4405
题意:一种游戏,在一维坐标中,从0点出发,每次都会摇股子,有1,2,3,4,5,6这几种,摇到哪个就前进几个整点,比如x点,摇到了2点,就到了x+2点上。
其中还有几个飞行航线,比如(x,y)意思就是在x点可以直接跳到y点,不用摇股子。到n点,或者大于n点就算赢,问赢的期望。
分析:和大富翁游戏是不是有点像~
如果没有飞行航线的话,那么就和上面题目一样了,状态方程为:
dp[i]=(1.0/6.0)*(dp[i+1]+dp[i+2]+dp[i+3]+dp[i+4]+dp[i+5]+dp[i+6])+1.0;
这个飞行航线,只用将dp[x]=dp[y]就行了~
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <vector>
using namespace std;
#define ll long long
#define mem(a,b) memset(a,b,sizeof(a))
const int maxn = 1e5+10;
double dp[maxn];
int vis[maxn];
vector<int> v[maxn];
int main()
{
int n,m;
while(scanf("%d %d",&n,&m)!=EOF&&(n+m))
{
for(int i=0;i<=100007;i++) {dp[i]=0;vis[i]=0;}
for(int i=0;i<=n;i++) v[i].clear();
for(int i=0;i<m;i++)
{
int x,y;
scanf("%d %d",&x,&y);
v[y].push_back(x);
}
for(int j=0;j<v[n].size();j++){//因为可能直接跳到n点的
dp[v[n][j]]=dp[n];
vis[v[n][j]]=1;
}
for(int i=n-1;i>=0;i--)
{
if(!vis[i])
dp[i]=(1.0/6.0)*(dp[i+1]+dp[i+2]+dp[i+3]+dp[i+4]+dp[i+5]+dp[i+6])+1.0;
for(int j=0;j<v[i].size();j++){
dp[v[i][j]]=dp[i];
vis[v[i][j]]=1;
}
vis[i]=1;
}
printf("%.4f\n",dp[0]);
}
return 0;
}
codeforces 867D
这个期望dp还是没有想明白……