骑士(利用step by step解题)
题目描述
给出一个空的国际象棋棋盘(8x8方格),棋子骑士放在其中一个方格上。国际象棋骑士走一步的8个方向如下图所示:
一开始骑士所在的格子是第x行第y列。如果骑士移动n次,每次随机均匀地挑选八个方向中的一个(可能是使骑士离开棋盘的方向),求在n次跳跃后它仍然在棋盘上的概率。一旦骑士离开了棋盘,它就无法再次进入。
输入格式
多组测试数据。
第一行,一个整数G,表示有G组测试数据。 1 <= G <= 10
每组测试数据格式:
第一行,三个整数: x, y,n。 1 <= x,y <=8。 1 <=n <=100。 一开始骑士所在的格子是第x行第y列。左下角格子是(1,1)
输出格式
共G行,共G行,每行一个实数,误差不超过0.0001。
输入样例
10
1 1 2
4 4 1
2 3 10
4 3 50
3 7 1
7 1 1
8 6 2
5 8 3
7 1 4
1 3 5
输出样例
0.1875
1.0
0.0522148497402668
8.356427906809618E-7
0.75
0.375
0.359375
0.28515625
0.1533203125
0.149078369140625
解题思路
题目大意:给出骑士最开始的位置,求骑士移动n次后,仍停留在棋盘上的概率
本题是不是很像一道dfs或bfs呢!经典的题目设定我们就用经典的解法去做,本题我们用dfs深度优先搜索。
但是我们要怎样深搜去求概率呢?由题可知,对于任意一步,我们都有8种跳法,经过n次跳跃之后,我们可以得到以下的搜索树:
这些状态都可以用
d
f
s
(
x
,
y
,
s
t
e
p
)
dfs(x,y,step)
dfs(x,y,step)来表示骑士当前在(x,y),还要走step步仍留在棋盘的概率。
d f s ( x , y , s t e p ) = d f s ( x + 1 , y + 2 , s t e p + 1 ) × 1 8 + d f s ( x + 2 , y + 1 , s t e p + 1 ) × 1 8 + d f s ( x + 2 , y − 1 , s t e p + 1 ) × 1 8 ⋯ dfs(x,y,step)=dfs(x+1,y+2,step+1)\times\frac{1}{8}+dfs(x+2,y+1,step+1)\times\frac{1}{8}+dfs(x+2,y-1,step+1)\times\frac{1}{8}\cdots dfs(x,y,step)=dfs(x+1,y+2,step+1)×81+dfs(x+2,y+1,step+1)×81+dfs(x+2,y−1,step+1)×81⋯
当(x,y)不在棋盘上时,这一步返回一个0,就不会计入答案。
当step=n时,且(x,y)在棋盘上,返回一个1,计入答案。
但是本题的数据范围很大,且重复的子问题很多,所以我们要用到记忆化搜索。
设 r e c [ x ] [ y ] [ s t e p ] rec[x][y][step] rec[x][y][step]记录骑士当前在(x,y),还要走step步仍留在棋盘的概率。
下一次如果碰巧遍历到这个点就可以直接返回值了。
总感觉没什么好说的,看代码注释。
代码
#include<bits/stdc++.h>
using namespace std;
int G,x,y,n;
int dx[10]={0,1,2,2,1,-1,-2,-2,-1};
int dy[10]={0,2,1,-1,-2,-2,-1,1,2};
double rec[10][10][110];
bool vis[10][10][110];
bool onboard(int x,int y)//判断是否在棋盘上
{
if(x<=8&&x>=1&&y<=8&&y>=1) return 1;
else return 0;
}
double dfs(int x,int y,int step)
{
if(onboard(x,y)==0) return 0.0;//如果不在棋盘上,那么就出局了
if(step==0) return 1.0;//如果这n步全部跳完了,那么成功
if(vis[x][y][step]==1) return rec[x][y][step];//记忆化
for(int i=1;i<=8;i++)//走八个方向
rec[x][y][step]+=(1.00/8.00)*dfs(x+dx[i],y+dy[i],step-1);//走到这一步的概率是八分之一
vis[x][y][step]=1;
return rec[x][y][step];
}
int main()
{
freopen("2799.in","r",stdin);
freopen("2799.out","w",stdout);
cin>>G;
for(int gr=1;gr<=G;gr++)
{
cin>>x>>y>>n;
memset(vis,0,sizeof(vis));
memset(rec,0.0,sizeof(rec));
cout<<fixed<<setprecision(6)<<dfs(x,y,n)<<endl;
}
return 0;
}