题目链接:
https://leetcode-cn.com/problems/cat-and-mouse/
题目大意:

在一张无向图中,老鼠开始处于1号点,猫开始处于2号点,0号点是洞(猫不能进入),猫鼠交替移动(老鼠先)。
若老鼠能进入洞中,即老鼠胜,输出1;若猫能抓住老鼠(猫鼠同在一共点),即猫胜,输出2;否则则为平局,输出0。
解题思路:
这题可以用状态转移,将初始状态转移到已知的胜负的状态中。
我们可以使用一个三维数组 dp[i][j][k]dp[i][j][k]dp[i][j][k] 表示当老鼠在 iii 位置,猫在 jjj 位置,游戏进行了 kkk 轮时的胜负关系。
那么,我们可以先把确定的胜负关系罗列一下:
1.当老鼠位于0号点位时,老鼠必胜,即 dp[0][j][k]=1dp[0][j][k]=1dp[0][j][k]=1
2.当猫鼠位于相同位置时,猫必胜,即 dp[x][x][k]=2dp[x][x][k]=2dp[x][x][k]=2
3.当游戏进行2*n轮之后,即可认定为是平局的情况,即 dp[i][j][2∗n]=0dp[i][j][2*n]=0dp[i][j][2∗n]=0
(猫鼠都进行了n轮游戏,若仍未能分出胜负,则代表至少存在1个点老鼠已经到达两次,则说明无论对于猫鼠,都已经不再存在必胜点了)
而对于状态转移,可以遵循几个关系:
1.若下一步存在能够必胜的状态,则可以直接转移过去,即可直接确定必胜关系,结束遍历
2.若下一步只存在必败状态,则可直接确定必败关系,结束遍历
3.若下一步存在仍不确定(或必和)的状态,可先移动至此,再继续寻找后续必胜状态
因为移动的先后关系,我们可以将奇数回合当为老鼠移动,而偶数回合即为猫移动
对此,只需再注意一个点,即猫不能去到0号点即可
上代码:
class Solution {
public:
int n,dp[55][55][105];
vector< vector<int> > p;
int catMouseGame(vector<vector<int>>& graph) {
n=graph.size();
p=graph;
memset(dp,-1,sizeof(dp));
return GetResult(1,2,0);
}
int GetResult(int x,int y,int turn)
{
if(turn>=2*n) //回合数大于2*n,返回和状态
return 0;
if(dp[x][y][turn]==-1)
{
if(x==0) dp[x][y][turn]=1; //老鼠入洞,老鼠胜
else if(x==y) dp[x][y][turn]=2; //猫抓到老鼠,猫胜
else dp[x][y][turn]=GetNext(x,y,turn); //若不能确定,则继续找
}
return dp[x][y][turn];
}
int GetNext(int x,int y,int turn)
{
int move=turn%2==0?x:y; //确定当前回合移动的对象(猫、鼠)
int defaultResult=move==x?2:1;
int result=defaultResult; //将初始胜负状态确定为必败
for(int i:p[move])
{
if(move==y&&i==0) //猫不能到达0号点
continue;
int nx=move==x?i:x;
int ny=move==y?i:y;
int next=GetResult(nx,ny,turn+1); //找下一个点的胜负关系
if(next!=defaultResult)
{
result=next;
if(next!=0) //若这个点不是和的状态(即必胜必败已定),即可退出遍历
break;
}
}
return result;
}
};
使用状态转移解决猫鼠游戏问题
该博客介绍了一种解决猫鼠游戏问题的方法,利用状态转移数组dp来记录游戏过程中猫和老鼠的位置及胜负情况。初始状态包括老鼠在洞口胜利、猫和老鼠在同一点猫胜利以及游戏超过一定轮数后的平局。通过递归查找下一个位置的胜负状态,最终确定游戏结果。代码中展示了如何实现这一策略,并特别注意了猫不能进入洞口的规则。
2992

被折叠的 条评论
为什么被折叠?



