2021ACM河北省赛:B棋盘

123 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第14天,点击查看活动详情

2021ACM河北省赛——B-棋盘

7-2 B-棋盘

Bob有一个 n×m 的棋盘,但是由于年代久远,这个棋盘左上角 (1,1) 的格子和右下角 (n,m) 的格子已经破损了。

现在Bob想知道是否存在一条路径,使得从起点走到终点能经过所有 n×m−2 个格子恰好一次。如果一个格子可以走到另一个格子,当且仅当两个格子至少有一条公共边。如果存在,请输出方案(如果有多种合法方案,输出任意一种即可),或者判断不存在。

输入格式:

输入仅一行,包含两个整数 n,m(2≤n,m≤1000),表示棋盘的大小。

输出格式:

如果存在合法方案,第一行输出YES,接下来 nm−2 行,每行一个坐标,其中第 i+1 行表示该路径所经过的第 i 个格子的坐标。如果有多条路径,输出任意一条即可。

如果不存在,输出NO

输入样例1:

2 2

输出样例1:

NO

输入样例2:

3 2

输出样例2:

YES
1 2
2 2
2 1
3 1

问题解析

一笔画问题,如果想从坐上走到右下且一格不重复,必须行数或列数有一个是奇数的情况下才可能成功。如果都是偶数,则不可能有合法路线。然后蛇形移动是最简便的了,如图:

屏幕截图 2022-10-12 211248.png

或者:

屏幕截图 2022-10-12 211341.png

我们判断行和列的奇偶性:

  • 如果行为奇数,我们按照红色路线输出路径;
  • 如果列为奇数,我们按照蓝色路线输出路径;
  • 如果都不为奇数,我们输出no。

AC代码

#include<iostream>
using namespace std;
#include<vector>
#include<algorithm>
#include<math.h>
#include<set>
#include <random>
#include<numeric>
#include<string>
#include<string.h>
#include<iterator>
#include<fstream>
#include<map>
#include<unordered_map>
#include<stack>
#include<list>
#include<queue>
#include<iomanip>
#include<bitset>#pragma GCC optimize(2)
#pragma GCC optimize(3)#define endl '\n'
#define int ll
#define PI acos(-1)
#define INF 0x3f3f3f3f
typedef long long ll;
typedef unsigned long long ull;
typedef pair<ll, ll>PII;
const int N = 4e5 + 50;
​
void solve()
{
    int n, m;
    cin >> n >> m;
    if (n % 2 == 1)
    {
        cout << "YES" << endl;
        for (int i = 1; i <= n; i += 2)
        {
            for (int j = 1; j <= m; j++)
            {
                if ((i != 1 || j != 1) && (i != n || j != m))
                    cout << i << " " << j << endl;
            }
            if (i + 1 > n)break;
            for (int j = m; j >= 1; j--)
            {
                if (((i+1) != 1 || j != 1) && ((i + 1) != n || j != m))
                    cout << i + 1 << " " << j << endl;
            }
        }
    }
    else if (m % 2 == 1)
    {
        cout << "YES" << endl;
        for (int i = 1; i <= m; i += 2)
        {
            for (int j = 1; j <= n; j++)
            {
                if ((i != 1 || j != 1) && (i != m || j != n))
                    cout << j << " " << i << endl;
            }
            if (i + 1 > m)break;
            for (int j = n; j >= 1; j--)
            {
                if (((i + 1) != 1 || j != 1) && ((i + 1) != m || j != n))
                    cout << j << " " << i+1 << endl;
            }
        }
    }
    else cout << "NO" << endl;
}
​
signed main()
{
​
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
    int t = 1;
    //cin >> t;
​
    while (t--)
    {
        solve();
    }
    return 0;
}