smzx 骑士 题解

捕获.PNG

捕获.PNG

记忆化搜索+概率。

\(dfs(x,y,step)\) 表示当前骑士在 \((x,y)\) 的位置上,走 \(step\) 步后仍在棋盘上的概率。

一个骑士一步可以跳 \(8\) 个不同的位置,所以走 \(step\) 步后的概率等于一步能跳到的 \(8\) 个位置中,每个位置走 \(step-1\) 步后在棋盘上的概率乘 \(\frac{1}{8}\)

可得 \(dfs(x,y,step)=dfs(x-2,y-1,step-1)\times\frac{1}{8}+dfs(x-2,y+1,step-1)\times\frac{1}{8}+\cdots\)

边界条件:当 \(step=0\) 时,返回 \(1\)

记得记忆化。

#include<iostream>
#include<cstdio>
using namespace std;
const int N=110,XY=20,F=10;
int g,x,y,n,fx[F]={0,-2,-2,-1,1,2,2,1,-1,},fy[F]={0,-1,1,2,2,1,-1,-2,-2};
double dp[XY][XY][N];
bool r[XY][XY][N];
double dfs(int dx,int dy,int step)//记忆化搜索
{
	int tx,ty;
	if(!step) return 1;//边界返回
	if(r[dx][dy][step]) return dp[dx][dy][step];//记忆化返回
	for(int i=1;i<=8;i++)//求递推式
	{
		tx=dx+fx[i],ty=dy+fy[i];
		if(tx>=1&&tx<=8&&ty>=1&&ty<=8) dp[dx][dy][step]+=dfs(tx,ty,step-1)*0.125;
	}
   //记忆化
	r[dx][dy][step]=true;
	return dp[dx][dy][step];
}
int main()
{
	scanf("%d",&g);
	while(g--)
	{
		scanf("%d%d%d",&x,&y,&n);
		//多测清空
		for(int i=1;i<=x;i++)
		{
			for(int j=1;j<=y;j++)
			{
				for(int k=1;k<=n;k++) r[i][j][k]=false,dp[i][j][k]=0;
			}
		}
		printf("%lf\n",dfs(x,y,n));
	}
	return 0;
}
posted @ 2024-07-29 22:25  MinimumSpanningTree  阅读(10)  评论(0)    收藏  举报