ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

CF1700E Serega the Pirate 解题报告

2022-07-02 15:02:50  阅读:157  来源: 互联网

标签:Serega int 特判 合法 yy xx CF1700E && Pirate


CF1700E Serega the Pirate 解题报告

link

Sol

参考了SA的做法

转换一下题意,如果存在题目要求的路径,则每个点的上下左右应至少有一个点的值是小于它本身的。

我们定义一个点的 为它的上下左右小于它的个数,若该点的度大于等于1,则该点合法;反之则不合法。

即:\(\texttt{交换任一点对,使图中所有点的度大于等于1(都合法)}\)

如果都合法,直接输出0;

易知交换2个点,最多影响到\((4 + 1) \times 2 = 10\)个点,即它的上下左右和它自己,所以不合法的点的数目若超过10个,就不是交换一次能解决的问题,特判为2输出即可。

大部分题解都是枚举所有不合法的点去和其他点挨个比较,但实际上可以挑 任意一个不合法点的上下左右及其本身 作为起始点。因为改变这五个位置可能让它变得合法,而若想满足题目要求,需要保证所有点都合法,其中就包括这个点,所以它一定得合法,因此只择一个不合法点作为起点就行。

有一个细节是交换的两个点的贡献不要算重了,就特判一下,其一 不要踩到枚举过作为起点的点 ,其二 特判一个点的横纵坐标减去另一个点的横纵坐标的差的绝对值的和是否大于1(形象理解就是两点是否在同一个\(6 \times 6\)的大方块中)即可

时间复杂度 \(O(nm)\)。

Code

#include <bits/stdc++.h>

using namespace std;

const int MN = 4e5 + 5;

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

int n, m, sum, X, Y, ans;
int a[MN];
bool vis[MN], bhf[MN];

inline int g(int x, int y) {
    return (x - 1) * m + y;
}

int calc(int x, int y) {
    if (a[g(x, y)] == 1) return 0;
    bool flag = false;
    for (int i = 1; i < 5; ++i) {
        int xx = x + dx[i], yy = y + dy[i];
        if (xx >= 1 && xx <= n && yy >= 1 && yy <= m && a[g(xx, yy)] < a[g(x, y)]) {
            flag = true;
            break;
        }
    }
    if (flag == true && bhf[g(x, y)]) return 1;
    else if (flag == false && !bhf[g(x, y)]) return -1;
    else return 0;
}

void solve(int x, int y) {
    for (int i = 1; i <= n; ++i) {
        for (int j = 1; j <= m; ++j) {
            if (vis[g(i, j)]) continue;
            swap(a[g(i, j)], a[g(x, y)]);
            int tot = 0;
            for (int k = 0; k < 5; ++k) {
                int xx = i + dx[k], yy = j + dy[k];
                if (xx >= 1 && xx <= n && yy >= 1 && yy <= m) tot += calc(xx, yy);
            }
            for (int k = 0; k < 5; ++k) {
                int xx = x + dx[k], yy = y + dy[k];
                if (xx >= 1 && xx <= n && yy >= 1 && yy <= m)
                    if (abs(xx - i) + abs(yy - j) > 1) tot += calc(xx, yy); //特判2
            }
            if (tot == sum) ans++;
            swap(a[g(i, j)], a[g(x, y)]);
        }
    }
}

signed main() {
    ios::sync_with_stdio(false), cin.tie(0);
    cin >> n >> m;
    for (int i = 1; i <= n; ++i)
        for (int j = 1; j <= m; ++j)
            cin >> a[g(i, j)];
    for (int i = 1; i <= n; ++i) {
        for (int j = 1; j <= m; ++j) {
            if (a[g(i, j)] == 1) continue;
            int cnt = 0;
            for (int k = 1; k < 5; ++k) {
                int xx = i + dx[k], yy = j + dy[k];
                if (xx >= 1 && xx <= n && yy >= 1 && yy <= m) cnt += a[g(xx, yy)] < a[g(i, j)];
            }
            if (cnt == 0) {
                // cout << i << ' ' << j << '\n';
                bhf[g(i, j)] = true;
                sum++;
                X = i, Y = j;
            }
        }
    }
    if (sum == 0) {
        puts("0");
        return 0;
    }
    if (sum > 10) {
        puts("2");
        return 0;
    }
    for (int i = 0; i < 5; ++i) {
        int xx = X + dx[i], yy = Y + dy[i];
        if (xx >= 1 && xx <= n && yy >= 1 && yy <= m) {
            vis[g(xx, yy)] = true; //特判1
            solve(xx, yy);
        }
    }
    if (ans) cout << 1 << ' ' << ans << '\n';
    else puts("2");
    return 0;
}

标签:Serega,int,特判,合法,yy,xx,CF1700E,&&,Pirate
来源: https://www.cnblogs.com/zjsqwq/p/16437571.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有