cf1472 F. New Year's Puzzle

题意:

\(2*n\) 网格,某些格子被 ban 了。现有无数的 \(1*2\)\(2*1\) 瓷砖,问能不能覆盖所有未 ban 的格子。

被 ban 的和范围外的格子不能被覆盖,未 ban 的每个格子只能被覆盖一次

思路:

满脑子国际象棋棋盘染色,没想到是个分类讨论模拟。。。

考虑最左边的列,

如果已满(上下两格都已被覆盖),删除这列,第二列变成新的第一列;

如果为空就竖着放,然后同样删除此列。这是因为如果第二列满,那只能放一个竖的;如果第二列为空,前两列要么放俩竖要么放俩横,不妨就放俩竖;如果第二列有一个,那只能在第一列放一竖,然后接着处理第二列;

如果有一个,那必定要往下一列伸出一格(代码中用 \(out\) 变量记录),然后也是删除第一列,这时第二列被改变了,与初始不同。当然这个过程如果冲突就寄了

void sol() {
    int n, m; cin >> n >> m;
    map<int,int> mp; //-1表示满
    while(m--) {
        int r, c; cin >> r >> c;
        mp[c] = mp[c] ? -1 : r;
    }
    int last = 0, out = 0; //前面伸过来的
    for(auto &[p, st]: mp) {
        if(last && out && (p-last)%2==0) out = 3 - out; last = p;
        if(out) {
            if(st != -1 && st != out) out = 0;
            else return cout << "NO\n", void();
        }
        else if(st != -1) out = 3 - st;
    }
    cout << (out ? "NO\n" : "YES\n");
}
posted @ 2022-05-25 21:07  Bellala  阅读(26)  评论(0)    收藏  举报