第三届辽宁省大学生程序设计竞赛:B-可莉的五子棋

269 阅读3分钟

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

第三届辽宁省大学生程序设计竞赛——B-可莉的五子棋

B-可莉的五子棋

题目描述

可莉最近沉迷于蒙德五子棋,她在棋盘上放了一些棋子。

蒙德五子棋的规则如下。

给定一个n*m的棋盘。棋盘上有两种棋子“1”和“2”,其中每种棋子分别计算得分。

假如相同种类的五个棋子连成相邻的一行,一列,或斜对角线的情况,每有五个这样的棋子,该种类棋子加1分。

可莉已经把她的棋子都摆在了棋盘上。

但是可莉不太聪明的样子,她希望你,聪明的旅行者,告诉她,她两种棋子的得分。

输入描述:

第一行两个整数n,m,表示棋盘的大小。
接下来输入一个n*m的矩阵,表示棋盘。
“1”,“2”表示该位置有对应的棋子。
“0”表示该位置没有棋子。

输出描述:

一行2个整数,以空格隔开,表示“1”,“2”两种棋子各自的得分。   

输入

20 20
10202022021000221222
22111122221221101010
11211001210010001210
02222120211010112111
21220011111022120012
00111101111212221010
22122012211221212111
22102022221121110211
20222121122221221121
10012221102212201222
12110201221022101111
02212201100112112111
22111222202221211110
12112222222122102121
21021120121212010221
10222001121022022112
11111201112100221021
12112102021200111100
21021021011222222202
12021221122012111212

输出

10 12

备注:

1<=n,m<=1000
可莉只是懒的算,才...才不是算不出来!

问题解析

对于当前的棋子,我们可以把它看作是4个来自不同且不对立的方向的延申。

比如对于坐标(x,y)的棋子,我们可以把它看作是(x,y-1)、(x-1,y-1)、(x-1,y)、(x-1,y+1)这四个方向的延申(如图,黄色格子可以是我们当前的格子)

屏幕截图 2022-10-25 203253.png

我们设置三维状态转移数组f,f[x] [y] [z]的意思是,对于位置(x,y)处的棋子,来自方向z的连续棋子数为f[x] [y] [z]。

当方向z的棋子与(x,y):

  • 相同时,有:f[x] [y] [z]=f[x+dx[z]] [y+dy[z]] [z]+1;
  • 不相同时,有:f[x] [y] [z]=1;

当f[x] [y] [z]>=5 时,当前棋子得分+1。

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 = 1050;
​
int a[N][N], f[N][N][5];
int dx[8] = { 0,-1,-1,-1,0,1,1,1 }, dy[8] = { -1,-1,0,1,1,1,0,-1 };
void solve()
{
    int n, m;
    cin >> n >> m;
    string s;
    unordered_map<int, int>mymap;
    for (int i = 1; i <= n; i++)
    {
        cin >> s;
        for (int j = 1; j <= m; j++)
        {
            a[i][j] = s[j-1] - '0';
            if (a[i][j] == 0)continue;
            for (int k = 0; k < 4; k++)
            {
                int x = i + dx[k], y = j + dy[k];
                
                if (a[x][y] == a[i][j])
                {
                    f[i][j][k] = f[x][y][k] + 1;
                    if (f[i][j][k] >= 5)
                    {
                        mymap[a[i][j]]++;
                    }
                }
                else 
                {
                    f[i][j][k] = 1;
                }
            }
        }
    }
    cout << mymap[1] << " " << mymap[2];
}
​
signed main()
{
​
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
    int t = 1;
    //cin >> t;
​
    while (t--)
    {
        solve();
    }
    return 0;
}