1. 程式人生 > 其它 >【Codeforces Round #693 (Div. 3) F】New Year's Puzzle

【Codeforces Round #693 (Div. 3) F】New Year's Puzzle

技術標籤:initluaehcacheshaderslam

題目連結

連結

翻譯

給你一個 \(2*n\) 的方格,讓你用 \(1*2\) 的骨牌,橫著或者豎著放,鋪滿整個方格。

其中有一些被黑色方塊阻擋,不能放骨牌。問你可不可行。

題解

首先考慮 整個方格 第一列,如果兩行都是空的。

那麼考慮第二列的幾種情況:

  • 第二列也是空的,那麼第一列放豎的沒問題。
  • 第二列有一個方格被堵住了,那麼第一列只能豎著放了,不然鋪不滿(注意這是第一列,它之前沒有列了)
  • 第二列有兩個方格都被堵住了,那麼第一列也同樣是豎著放。

綜上所述,第一列如果兩行都是空的,那麼就豎著放一個就行。

這樣就可以不斷地 \(Reduce\)

問題。然後如果新的第一列還是空的,就不斷縮減。

當然,如果第一列兩行都被堵住了,那麼同樣的也可以縮減問題,因為這一列不用放骨牌...

這樣,我們的問題的第一列就總是隻有一個方格被堵住的情況了。

這個時候我們只能放一個橫的骨牌,會突出來一部分。而且,如果它的右邊仍然是兩行都是空著的情況,那麼又得繼續橫著放一個。

直到遇到某個位置也恰好只有一行被堵住,則需要判斷一下能不能剛好填滿兩行。所以中間的大概 \(n-m\) 個空格可以直接跳過。

這裡能否填滿兩行的情況需要根據前後兩個 只有一行被堵住 的列的座標差的奇偶性來判斷,為奇數,則被堵住的行號應該相同。否則,應該不同。

程式碼

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

const int N = 2e5;
const LL MOD = 1e9 + 7;
const int K = 5000;

int n, m;
map<int, int> dic;

int main() {
	#ifdef LOCAL_DEFINE
		freopen("in.txt", "r", stdin);
	#endif
	ios::sync_with_stdio(0), cin.tie(0);
	int T;
	cin >> T;
	while (T--) {
		dic.clear();
		cin >> n >> m;
		for (int i = 1; i <= m; i++) {
			int r, c;
			cin >> r >> c;
			dic[c] |= (1 << (r - 1));
		}
		//reduce
		map<int,int>::iterator it = dic.begin();
		while (it != dic.end()) {
			pair<int, int> temp = *it;
			if (temp.second == 0 || temp.second == 3) {
				m--;
				it++;
				continue;
			}
			else {
				break;
			}
		}
		if (it == dic.end()) {
			cout << "YES" << endl;
			continue;
		}
		//it.second == 2 || it.second == 1
		pair<int,int> pre = (*it);
		it++;
		bool ok = true;
		while (it != dic.end()) {
			if (pre.second == 0 || pre.second == 3) {
				pre = (*it);
				it++;
				continue;
			}
			int temp = (*it).second;
			int delta = (*it).first - pre.first;
			if (temp == 0) {
				if (delta%2 == 0) {
					pre.second = 3 - pre.second;
				}
				pre.first = (*it).first;
			}
			else if (temp == 1 || temp == 2){
				if (delta % 2 == 0) {
					if (temp != pre.second) {

					}
					else {
						ok = false;
						break;
					}
				}
				else {
					if (temp == pre.second) {

					}
					else {
						ok = false;
						break;
					}
				}
				pre = *it;
				pre.second = 3;
				it++;
			}
			else {
				//temp==3
				if (pre.second != 0 && pre.second != 3) {
					ok = false;
					break;
				}
				it++;
			}
		}
		if (!ok || pre.second == 1 || pre.second == 2) {
			cout << "NO" << endl;
		}
		else {
			cout << "YES" << endl;
		}
	}
	return 0;
}