【基础算法】棋盘游戏问题

95 阅读3分钟

🌹作者:云小逸
📝个人主页:云小逸的主页
📝Github:云小逸的Github
🤟motto:要敢于一个人默默的面对自己,==强大自己才是核心==。不要等到什么都没有了,才下定决心去做。种一颗树,最好的时间是十年前,其次就是现在!学会自己和解,与过去和解,努力爱自己。==希望春天来之前,我们一起面朝大海,春暖花开!==🤟 👏专栏:C++👏 👏专栏:Java语言👏👏专栏:Linux学习👏
👏专栏:C语言初阶👏👏专栏:数据结构👏👏专栏:备战蓝桥杯👏

@TOC


前言

今天我们继续学习算法,加油。这篇文章写的是三元组问题。希望这篇可以有幸帮助到你,码字不易,请多多支持。 在这里插入图片描述


AcWing 3480. 棋盘游戏

题目描述

给定一个 n×nn\times n 的棋盘,黑色棋子的位置为 (x1,y1)(x_1, y_1),白色棋子的位置为 (x2,y2)(x_2, y_2)

两个棋子都可以进行如下三种移动操作:

  • 上下左右移动一格;
  • 沿着竖直或者水平的方向一直走到棋盘的边界;
  • 沿着对角线的方向一直走到棋盘的边界。

两个棋子在同一个格子上时,黑方获胜。

求最少需要几步才能使黑方获胜,或者判断黑方是否有必胜策略。

输入格式

第一行包含一个整数 nn

第二行包含两个整数 x1,y1x_1,y_1

第三行包含两个整数 x2,y2x_2,y_2

输出格式

如果黑方有必胜策略,输出最少需要几步才能使黑方获胜。

如果黑方无必胜策略,输出 Impossible。

数据范围

1n500,1x1,y1,x2,y2n1\leq n\leq 500, 1\leq x_1,y_1,x_2,y_2\leq n

输入样例1:

3
1 1
3 3

输出样例1:

2

输入样例2:

3
1 1
2 2

输出样例2:

Impossible

解题思路

本题考虑使用广搜求解,由于有两个棋子,可以从两个棋子分别出发,对于每一个状态,只有两种情况,一种是黑子胜利,一种是未分胜负,因此可以将状态设为当前黑子的位置和白子的位置,这样一个状态只会被搜到一次,避免了重复搜寻。

需要注意的是,由于黑子胜利的情况下,需要记录黑子胜利的步数,所以可以在队列中存储一个pair,第一个元素是当前状态,第二个元素是当前步数,这样就可以记录黑子胜利的步数了。

C++代码

#include <iostream>
#include <cstring>
#include <queue>
using namespace std;

const int N = 510;

int n;
int h1, l1, h2, l2;
bool st[N][N][2];
typedef pair<pair<int, int>, int> PII;

int bfs()
{
    queue<PII> q;
    q.push({{h1, l1}, 0});
    q.push({{h2, l2}, 0});
    st[h1][l1][0] = true;
    st[h2][l2][1] = true;

    int dx[4] = {-1, 0, 1, 0};
    int dy[4] = {0, 1, 0, -1};

    while (q.size())
    {
        auto t = q.front();
        q.pop();
        int x = t.first.first, y = t.first.second;
        int step = t.second;
        int k = st[x][y][0];

        for (int i = 0; i < 4; i ++ )
        {
            int a = x + dx[i], b = y + dy[i];
            if (a < 1 || a > n || b < 1 || b > n) continue;
            if (st[a][b][k]) continue;
            if (a == h2 && b == l2) return step + 1;

            st[a][b][k] = true;
            q.push({{a, b}, step + 1});
        }

        for (int i = -1; i <= 1; i += 2)
            for (int j = -1; j <= 1; j += 2)
            {
                int a = x + i, b = y + j;
                while (a >= 1 && a <= n && b >= 1 && b <= n && !st[a][b][k])
                {
                    if (a == h2 && b == l2) return


最后

十分感谢你可以耐着性子把它读完和我可以坚持写到这里,送几句话,对你,也对我:

1.把时间尺度拉长,拉长十年看当下

2.不说负面情绪,只描述事实;

3.越专注于过好自己,能量和幸运越会照顾你; 只解决问题,不做没有意义的担心,输了就认;

4.学会原谅自己,要允许自己做错事,允许自己出现情绪波动,我知道你已经很努力很努力在做好了

5.所有你害怕的、想逃避的事情,最终都要面对,既然这样不如选择坦然面对。即使结果不如人愿,没关系,至少这个过程是享受的,而不是一路带着恐惧和害怕。

最后如果觉得我写的还不错,请不要忘记==点赞==✌,==收藏==✌,加==关注==✌哦(。・ω・。)

愿我们一起加油,奔向更美好的未来,愿我们从懵懵懂懂的一枚==菜鸟==逐渐成为==大佬==。加油,为自己点赞!