[poj 3853]Loops[概率DP入门题]

这种题主要就是推状态转移方程..推公式
解析:
设dp[i][j]表示(i,j)到(R,C)需要消耗的能量[这个定义很重要!]
则:
dp[i][j]=p1[i][j]*dp[i][j]+p2[i][j]*dp[i][j+1]+p3[i][j]*dp[i+1][j]+2;(走一步,额外消耗能量2)
化简得到:
dp[i][j]=p2[i][j]*dp[i][j+1]/(1-p1[i][j])+p3[i][j]*dp[i+1][j]/(1-p1[i][j])+2/(1-p1[i][j]);
注意一种情况就是p1[i][j]==1的情况。(除0错误)
题目只是保证答案小于1000000.但是有的点可能永远都不可能到达的。
所以这样的点出现p1[i][j]是允许的。
否则就会WA了。


转自:http://www.cnblogs.com/kuangbin/archive/2012/10/02/2710606.html

#include<cstdio>
#include<cmath>
using namespace std;
const int MAXN=1010;
const double eps=1e-5;
double dp[MAXN][MAXN];
double p1[MAXN][MAXN];
double p2[MAXN][MAXN];
double p3[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",&p1[i][j],&p2[i][j],&p3[i][j]);
        dp[R][C]=0;///倒着推!
        for(int i=R;i>=1;i--)
          for(int j=C;j>=1;j--)
          {
              if(i==R&&j==C)continue;
              if(fabs(1-p1[i][j])<eps)continue;
              dp[i][j]=p2[i][j]/(1-p1[i][j])*dp[i][j+1]+p3[i][j]/(1-p1[i][j])*dp[i+1][j]+2/(1-p1[i][j]);
          }
        printf("%.3lf\n",dp[1][1]);
    }
    return 0;
}

自己敲一遍:

#include <cstdio>
#include <cmath>
using namespace std;
const int MAXN = 1005;
const double EPS = 1e-5;
double dp[MAXN][MAXN],p1[MAXN][MAXN],p2[MAXN][MAXN],p3[MAXN][MAXN];
/**
dp[i][j] 表示从(i,j)到(R,C)耗费的能量
状态转移:
dp[i][j] = (p2[i][j]*dp[i+1][j] + p3[i][j]*dp[i][j+1] + 2) / (1 - p1[i][j]);
注意避免除0错误
**/
int main()
{
    int R,C;
    while(scanf("%d%d",&R,&C)==2)
    {
        for(int i=1;i<=R;i++)
            for(int j=1;j<=C;j++)
                scanf("%lf%lf%lf",p1[i]+j,p2[i]+j,p3[i]+j);
        dp[R][C] = 0;///由于没有越界的操作,也不涉及"坑"的值,也就不需要memset了,只要初始化终点即可
        for(int i=R;i>0;i--)
            for(int j=C;j>0;j--)
            {
                if(i==R && j==C)    continue;
                if(fabs(1 - p1[i][j])<EPS)  continue;///为什么这里不赋值?
                ///如果到达这里的概率是p,那么从这里到终点的能量应该是INF,那么总的期望..?
                ///显然也是INF.也就是说只要有可能走不出,那么期望就是走不出.
                ///从AC的情况反推数据,应该是,有p1==1的点,但是左和上数据[保证]不会走到这一点
                ///所以这一点的值是无所谓的,只要在计算它自己的时候避免一下除零错误,跳过就行了
                ///好吧,其实题目说<1000000,意思不只是限制在int内,还表明了没有INF的情况...
                dp[i][j] = (p2[i][j]*dp[i][j+1] + p3[i][j]*dp[i+1][j] + 2) / (1 - p1[i][j]);
            }
        printf("%.3lf\n",dp[1][1]);
    }
}

但是目测很慢的样子...


你可能感兴趣的:([poj 3853]Loops[概率DP入门题])