HDU44065 Aeroplane chess

版权声明:转载请注明出处 https://blog.csdn.net/FSAHFGSADHSAKNDAS/article/details/81749020

链接

http://acm.hdu.edu.cn/showproblem.php?pid=4405

题解

这是一道概率DP入门题
如果正着 D P ,遇到的问题就是一个点的前驱可能多余或者少于 6 ,因此我必须建一个 D A G 然后统计入度,以确定我转移的时候除以多少
但是倒着推,我就可以放心地除以 6 了,只是我在面临那些能飞的点时需要处理一下
f [ i ] 表示从 i 走到终点的期望步数,那么 f [ i ] = 1 + j = 1 6 1 6 f [ l a s t [ i + j ] ] ,其中 l a s t [ k ] 表示从 k 点能飞到的最后一个点

代码

//概率DP
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <cctype>
#define maxn 101000
#define cl(x,y) memset(x,y,sizeof(x))
#define eps 1e-8
using namespace std;
int last[maxn], N, M;
double f[maxn];
int dfs(int pos)
{
    if(!last[pos] or last[pos]==pos)return last[pos]=pos;
    return last[pos]=dfs(last[pos]);
}
int read(int x=0)
{
    int c, f=1;
    for(c=getchar();!isdigit(c);c=getchar())if(c=='-')f=-1;
    for(;isdigit(c);c=getchar())x=(x<<1)+(x<<3)+c-48;
    return f*x;
}
int init()
{
    int i, a, b;
    cl(last,0), cl(f,0);
    N=read(), M=read();
    if(!N and !M)return 0;
    for(i=1;i<=M;i++)a=read(), b=read(), last[a]=b;
    for(i=1;i<=N;i++)dfs(i);
    return 1;
}
void dp()
{
    int i, j;
    double ans=0;
    for(i=N-1;i>=0;i--)
        if(i==last[i])
        { 
            f[i]=1; 
            for(j=1;j<=6 and i+j<=N;j++)f[i]+=f[last[i+j]]/6.0;
        } 
    printf("%.4lf\n",f[0]);
}
int main()
{
    while(init())dp();
    return 0;
}

猜你喜欢

转载自blog.csdn.net/FSAHFGSADHSAKNDAS/article/details/81749020