2026牛客寒假算法基础集训营3 D. 系ぎて(最短路/分类讨论)

题目

思路来源

heltion代码、International_River代码

题解

找到一条1到1的最短路,记录前驱,标记成不可达,然后再找2到2的最短路

对称的,先找1再找2,和先找2再找1都跑一遍,有一个找到就是有解,否则就是无解

这个是常规做法

比较惊艳的是这个分类讨论,

只要出现以下三种情况就无解,否则就有解

  1. 交叉

  2. 卡角(两个数字把一个数字堵在一个角落)

  3. 四个数字均位于四条边上,且顺时针考虑它们的时候,第一个数字和第三个数字是同一个数字

代码1(最短路)

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
#define all(x) (x).begin(),(x).end()
typedef long long i64;
typedef pair<int, int> pii;

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

bool solve(vector<string> mp, char a, char b) {
    // cerr << a << b << endl << endl;
    int n = mp.size(), m = mp[0].length();
    vector f(n, vector<pii>(m, pii(-1, -1)));
    queue<pii> q; pii p;
    for(int i = 0; i < n; i++) {
        for(int j = 0; j < m; j++) {
            if(mp[i][j] == a) {
                if(q.empty()) {
                    q.push(pii(i, j));
                    mp[i][j] = '4';
                } else {
                    p = {i, j};
                }
            }
        }
    }
    while(!q.empty()) {
        auto [u, v] = q.front();
        q.pop();
        for(int i = 0; i < 4; i++) {
            int nu = u + dx[i];
            int nv = v + dy[i];
            if(nu < 0 || nv < 0 || nu >= n || nv >= m) continue;
            if(mp[nu][nv] != '0' && mp[nu][nv] != a) continue;
            f[nu][nv] = {u, v};
            mp[nu][nv] = '3';
            q.push({nu, nv});
        }
    }
    if(f[p.first][p.second].first == -1) return false;
    while(p.first != -1) {
        mp[p.first][p.second] = a;
        p = f[p.first][p.second];
    }
    for(int i = 0; i < n; i++) {
        for(int j = 0; j < m; j++) {
            if(mp[i][j] == '3') {
                mp[i][j] = '0';
            }
        }
    }
    // for(auto s : mp) cerr << s << endl; cerr << endl;

    for(int i = 0; i < n; i++) {
        for(int j = 0; j < m; j++) {
            if(mp[i][j] == b) {
                if(q.empty()) {
                    q.push(pii(i, j));
                    mp[i][j] = '4';
                } else {
                    p = {i, j};
                }
            }
        }
    }
    while(!q.empty()) {
        auto [u, v] = q.front();
        q.pop();
        for(int i = 0; i < 4; i++) {
            int nu = u + dx[i];
            int nv = v + dy[i];
            if(nu < 0 || nv < 0 || nu >= n || nv >= m) continue;
            if(mp[nu][nv] != '0' && mp[nu][nv] != b) continue;
            f[nu][nv] = {u, v};
            mp[nu][nv] = '3';
            q.push({nu, nv});
        }
    }
    if(f[p.first][p.second].first == -1) return false;

    return true;
}

void solve() {
    int n, m; cin >> n >> m;
    vector<string> mp(n);
    for(auto &s : mp) cin >> s;
    bool yes = solve(mp, '1', '2') || solve(mp, '2', '1');
    cout << (yes ? "YES" : "NO") << endl;
}

int main() {
    ios::sync_with_stdio(0);
    cin.tie(0), cout.tie(0);
    int T; cin >> T;
    while(T--) solve();
    return 0;
}

代码2(分类讨论)

rust 复制代码
use std::{
    cell::RefCell,
    fmt::Debug,
    io::{BufWriter, Read, Stdout},
    str::{FromStr, SplitAsciiWhitespace},
};
thread_local! {
    static INPUT: RefCell<SplitAsciiWhitespace<'static>> = RefCell::<SplitAsciiWhitespace<'static>>::new({
        let mut input = String::new();
        std::io::stdin().read_to_string(&mut input).unwrap();
        Box::leak(input.into_boxed_str()).split_ascii_whitespace()
    });
    pub static OUTPUT: RefCell<BufWriter<Stdout>> = RefCell::new(BufWriter::new(std::io::stdout()));
}
pub fn read<T: FromStr>() -> T
where
    T::Err: Debug,
{
    INPUT.with(|input| input.borrow_mut().next().unwrap().parse().unwrap())
}
pub fn read_string() -> Vec<u8> {
    INPUT.with(|input| input.borrow_mut().next().unwrap().as_bytes().to_vec())
}
#[macro_export]
macro_rules! expand {
    ($arg:expr) => {
        $arg.into_iter()
            .map(|x| x.to_string())
            .collect::<Vec<_>>()
            .join(" ")
    };
}
#[macro_export]
macro_rules! output {
    ($($arg:expr),*) => {
        OUTPUT.with(|output| {
            use std::io::Write;
            writeln!(output.borrow_mut(), "{}", [$($arg.to_string()),*].join(" ")).unwrap();
        });
    };
}
#[macro_export]
macro_rules! debug {
    ($($arg:expr),*) => {
        #[cfg(debug_assertions)]
        eprintln!("[{}:{}] {}", file!(), line!(), [$(format!("{} = {:?}", stringify!($arg), $arg)),*].join(", "));
    };
}
fn main() {
    fn solve() -> &'static str {
        let n: usize = read();
        let m: usize = read();
        let s: Vec<_> = (0..n).map(|_| read_string()).collect();
        for i in 0..n - 1 {
            for j in 0..m - 1 {
                if s[i][j] != b'0'
                    && s[i + 1][j] != b'0'
                    && s[i][j + 1] != b'0'
                    && s[i + 1][j + 1] != b'0'
                {
                    if s[i][j] == s[i + 1][j + 1] {
                        return "NO";
                    }
                }
            }
        }
        let corner = [
            ((0, 0), (0, 1), (1, 0)),
            ((0, m - 1), (0, m - 2), (1, m - 1)),
            ((n - 1, 0), (n - 2, 0), (n - 1, 1)),
            ((n - 1, m - 1), (n - 2, m - 1), (n - 1, m - 2)),
        ];
        for &((x, y), (a, b), (c, d)) in &corner {
            if s[x][y] != b'0' && s[a][b] != b'0' && s[c][d] != b'0' {
                if s[a][b] == s[c][d] {
                    return "NO";
                }
            }
        }
        let mut answer = vec![];
        for i in 0..m - 1 {
            if s[0][i] != b'0' {
                answer.push(s[0][i]);
            }
        }
        for i in 0..n - 1 {
            if s[i][m - 1] != b'0' {
                answer.push(s[i][m - 1]);
            }
        }
        for i in (1..m).rev() {
            if s[n - 1][i] != b'0' {
                answer.push(s[n - 1][i]);
            }
        }
        for i in (1..n).rev() {
            if s[i][0] != b'0' {
                answer.push(s[i][0]);
            }
        }
        if answer.len() == 4 && answer[0] == answer[2] {
            return "NO";
        }
        "YES"
    }
    for _ in 0..read() {
        output!(solve());
    }
}
相关推荐
拼好饭和她皆失17 天前
图论:拓扑排序讲解,以及 Dijkstra算法,Bellman-Ford算法,spfa算法,Floyd算法模板大全
算法·图论·最短路
罗湖老棍子1 个月前
最优乘车(travel)(信息学奥赛一本通- P1377)
算法·图论·bfs·最短路·字符串流·单向边
惆怅客1231 个月前
UVa1409/LA4019 Go to Class
最短路·dijkstra·计算几何·运动规划·离散化·icpc·uva
闻缺陷则喜何志丹1 个月前
【计算几何 最短路 动态规划】P1354 房间最短路问题
数学·算法·动态规划·最短路·计算几何·洛谷
您好啊数模君2 个月前
数学建模优秀论文算法-实时动态网络的dijkstra算法
数学建模·最短路·dijkstra
Espresso Macchiato4 个月前
Leetcode 3698. Split Array With Minimum Difference
leetcode medium·分类讨论·leetcode周赛469·leetcode 3698
一只小蒟蒻7 个月前
DFS 迷宫问题 难度:★★★★☆
算法·深度优先·dfs·最短路·迷宫问题·找过程
你的冰西瓜7 个月前
C++ 中最短路算法的详细介绍
c++·算法·图论·最短路
LunaGeeking8 个月前
重要的城市(图论 最短路)
c++·算法·编程·图论·最短路·floyd