[CF1472F] New Year's Puzzle - 状态压缩dp

[CF1472F] New Year's Puzzle

Description

给你一个 \(2\times n\) 的长方形,里面有 \(m\) 的格子被挡住了,可不可以只用 \(1\times 2\) 和 \(2\times 1\) 的小长方形盖住原来 \(2\times n\) 的长方形没被挡住的部分。

Solution

首先,连续的空行可以保持奇偶性不变压缩,这样做出一个等效的,\(n \le 2m\) 矩形,转置一下方便处理

设 \(f[i][0]\) 表示前 i 行处理妥善,是否可能

设 \(f[i][1]\) 表示前 i 行处理,剩下 \(a[i][1]\) 没有填充

设 \(f[i][2]\) 表示前 i 行处理,剩下 \(a[i][2]\) 没有填充

如果 \(a[i][1]=0, a[i][2]=0\),那么 \(0-0,1-2,2-1\)

如果 \(a[i][1]=1, a[i][2]=0\),那么 \(0-2,2-0\)

如果 \(a[i][1]=0, a[i][2]=1\),那么 \(0-1,1-0\)

如果 \(a[i][1]=1, a[i][2]=1\),那么 \(0-0\)

#include <bits/stdc++.h>
using namespace std;

#define int long long

#define tr(x, y) f[i][x] |= f[i - 1][y]

void solve()
{
    int n, m;
    cin >> n >> m;
    vector<pair<int, int>> block;
    map<int, int> mp;
    block.push_back({0, 0});
    for (int i = 1; i <= m; i++)
    {
        int x, y;
        cin >> x >> y;
        block.push_back({x, y});
        mp[y]++;
    }
    int last = 0;
    int ind = 0;
    for (auto &[x, y] : mp)
    {
        if ((x - last) & 1)
            y = ++ind;
        else
            ++ind, y = ++ind;
        last = x;
    }
    if (last < n)
        ++ind;

    // now: ind * 2
    vector<vector<int>> a(ind + 2, vector<int>(4));
    for (int i = 1; i <= m; i++)
    {
        auto [x, y] = block[i];
        y = mp[y];
        a[y][x] = 1;
    }

    // dp
    vector<vector<int>> f(ind + 2, vector<int>(4));
    f[0][0] = 1;
    for (int i = 1; i <= ind; i++)
    {
        if (a[i][1] == 0 && a[i][2] == 0)
        {
            tr(0, 0);
            tr(1, 2);
            tr(2, 1);
        }
        else if (a[i][1] == 0 && a[i][2] == 1)
        {
            tr(0, 1);
            tr(1, 0);
        }
        else if (a[i][1] == 1 && a[i][2] == 0)
        {
            tr(0, 2);
            tr(2, 0);
        }
        else
        {
            tr(0, 0);
        }
    }

    for (int i = 1; i <= ind; i++)
    {
        // cout << a[i][1] << " " << a[i][2] << endl;
    }

    // cout << endl;

    for (int i = 1; i <= ind; i++)
    {
        // cout << f[i][0] << " " << f[i][1] << " " << f[i][2] << endl;
    }

    // out
    cout << (f[ind][0] ? "YES" : "NO") << endl;
}

signed main()
{
    ios::sync_with_stdio(false);
    int t;
    cin >> t;
    while (t--)
        solve();
}
上一篇:信息学奥赛一本通(C++)在线评测系统——基础(一)C++语言——1106:年龄与疾病


下一篇:hdu 1106 排序