22.1.4猫和老鼠

两位玩家分别扮演猫和老鼠,在一张 无向 图上进行游戏,两人轮流行动。

图的形式是:graph[a] 是一个列表,由满足 ab 是图中的一条边的所有节点 b 组成。

老鼠从节点 1 开始,第一个出发;猫从节点 2 开始,第二个出发。在节点 0 处有一个洞。

在每个玩家的行动中,他们 必须 沿着图中与所在当前位置连通的一条边移动。例如,如果老鼠在节点 1 ,那么它必须移动到 graph[1] 中的任一节点。

此外,猫无法移动到洞中(节点 0)。

然后,游戏在出现以下三种情形之一时结束:

如果猫和老鼠出现在同一个节点,猫获胜。
如果老鼠到达洞中,老鼠获胜。
如果某一位置重复出现(即,玩家的位置和移动顺序都与上一次行动相同),游戏平局。
给你一张图 graph ,并假设两位玩家都都以最佳状态参与游戏:

如果老鼠获胜,则返回 1;
如果猫获胜,则返回 2;
如果平局,则返回 0 。

/*
猫鼠大战(动态规划+DFP)
1.首先该题只用深度优先遍历算法即可求解,但是执行的效率比较低下
2.在猫鼠每走一步都是在朝着自己不输的情况下进行的,所有在试探某一步的状态时都需要用深度
递归来确定这一步到游戏结束之前的状态,如果当前状态即不为赢。
3.在递归时使用了三维数组来记录走过的状态,以便在以后的试探中遇到相同的局面(比如 (0,2,3)->(1,5,3)->(2,5,4)和(0,2,6)->(1,5,6)->(2,5,4))
那么这时第三个局面就是相同的,通过三维表的记录即可获得状态。
4.在判断某个局面状态时是根据所有下一可走步的状态来确定的,如果有获胜的局就立即返回,千万注意只要下一步有和局的状态那么
当前状态就是和局(里面可能会有败局),只有全是败局当前状态才能被标记为败局(对方的胜局)。
/
#include
#include
#include
using namespace std;
class catMouse
{
public:
vector<vector> graph;
vector<vector<vector>> a;
catMouse();
~catMouse();
int catMouseGame(vector<vector>& graph);
int playgame( int c,int m,int t);
};
catMouse::catMouse()
{
}
catMouse::~catMouse()
{
}
int catMouse::catMouseGame(vector<vector>& graph)
{
this->graph = graph;
int count = graph.size();//节点数
int rc = 0;
this->a.resize(count
2);//定义游戏局面 a[轮次][猫的位置][老鼠的位置]
for (int i = 0; i < count
2; i++)
a[i].resize(count);
for (int i = 0; i < count
2; i++)
for (int j = 0; j < count; j++)
a[i][j].resize(count);
for (int i = 0; i < count2; i++)
for (int j = 0; j < count; j++)
for (int k = 0; k < count; k++)
a[i][j][k]=-1;//初始化局面
rc = playgame(2, 1, 0);
return rc;
}
int catMouse::playgame(int c,int m,int t)
{
int count = graph.size(),rc,flag=0;//rc是返回值,flag是判断是否出现过和局
int cur,nc,nm;//当前移动对象,下一个局面猫鼠位置
if(t>=count
2)//和局返回
{
return 0;
}
if(a[t][c][m]<0)//未出现的局面
{
if (m0)//老鼠胜局,猫的败局
{
a[t][c][m] = 1;
return 1;
}
else if(m
c)//猫的胜局,鼠的败局
{
a[t][c][m] = 2;
return 2;
}
else//查看所有可走步的状态
{
cur = t % 2 == 0 ? m : c;//获取当前移动的对象(学会用三目运算符)
for(int i:graph[cur])//遍历所有可走情况
{
if(curc&&i0)//若是猫则无法走零
continue;
nc = cur == c ? i : c;//获取下一个局面
nm = cur == m ? i : m;
rc = playgame(nc, nm, t + 1);//查看如果走了这步会不会赢
if((curc&&rc2)||(curm&&rc1))//如果赢就退出
{
a[t][c][m]=rc;
return rc;
}
if(rc0)//出现和局
flag=1;
}
a[t][c][m] = flag
1?0:rc;//是否出现和局,如果是标志为和局,否则就是败局
}
}
return a[t][c][m];
}
int main()
{
vector<vector> graph = {{1,3}, {0}, {3}, {0,2}};//[[2,3],[2],[0,1],[0,4],[3]]
catMouse a;
cout << a.catMouseGame(graph);
return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值