POJ 3756 Chess Game【DP求期望】

POJ 3756 Chess Game

核心算法 dp
分析:
graph[i]记录在格子i处前进的步数
stop[i]标记在格子i处是否停一次
dp[i][j]表示第j部到达格子i的概率
则  初始化下dp[0][0]=1;
若已知dp[i][j],现在掷骰子得点数为k,移动到格子curto = i+k;
如果格子curto处为暂停,则将当前概率加至dp[curto][i+2]处
否则,curto 首先根据graph[curto]信息移动,将概率加至相应位置dp[curto][i+1]即可

  ans = sum(dp[n][i]*i)(i=0,1,2,...N)
PS:当ans = 0时输出Impossible!

 

#include<stdio.h>

#include<string.h>

const int N = 1001;//最多需要步数

const int M =105;//格子数

int graph[M];//表示第i格是前进还是后退

bool stop[M];//表示该格是否该停一次

double dp[M][N];//dp[i][j]表示第j步到达第i格的概率

int main()

{

	int nf,ns,nb,n,id,step;

	while(scanf("%d",&n)!=EOF)

	{

		memset(graph,0,sizeof(graph));

	    memset(stop,false,sizeof(stop));

		memset(dp,0,sizeof(dp));

		dp[0][0]=1;//第0步在0格的概率为1

		scanf("%d",&nf);//前进信息

		while(nf--)

		{

			scanf("%d%d",&id,&step);

			graph[id]+=step;

		}



		scanf("%d",&nb); //后退信息

		while(nb--)

		{

			scanf("%d%d",&id,&step);

			graph[id]-=step;

		}



		scanf("%d",&ns);//暂停信息

		while(ns--)

		{

			scanf("%d",&id);

			stop[id]=true;

		}



		double once = 1.0/6;

		int i,j,k;

		for(i=1;i<N;i++)

		{

			for(j=0;j<n;j++)

			{

				if(dp[j][i-1]==0)continue;

				for(k=1;k<=6;k++)

				{

					double top = once*dp[j][i-1];

					int curto = k+j;

					if(curto>n)

					{

                      curto = 2*n-curto;

					}



					if(stop[curto])//暂停

					{

						dp[curto][i+1]+=top;

						continue;

					}

					curto+=graph[curto];

					if(curto>n)curto = 2*n-curto;

					if(curto<0)curto=-curto;

					dp[curto][i]+=top;

				}

			}

		}



		double ans = 0;

		for(i=0;i<N;i++)

		{

			ans+=dp[n][i]*i;

		}

		if(ans>0)

		printf("%.2lf\n",ans);

		else

			printf("Impossible\n");

	}

	return 0;

}

你可能感兴趣的:(game)