CF1990D Grid Puzzle 題解

SunsetLake發表於2024-07-24

思路

首先有一個觀察:對於 \(a_i > 4\) 的行,一定只會用一次操作二,因為若要用操作一,那麼將 \(i,i + 1\) 都變白至少都需要 \(3\) 次操作,用操作二隻需要兩次。於是我們只考慮 \(a_i \le 4\) 的情況。

根據上面這個觀察,我們可以知道對於兩行 \(i,i + 1\)\(2\)\(2 \times 2\) 和用兩次操作二是等價的,於是對於放 \(2\)\(2 \times 2\) 的行都將其換成用兩次操作二。那麼,每行就最多隻會有 \(1\)\(2 \times 2\) 的方格,考慮其放在那裡(若存在):一定不會在 \(2\)\(3\) 列之間,因為每一行的黑格子是從 \(1 \sim a_i\) 連續的,不能覆蓋 \(1\) 一定不優。故只會在 \(1,2\)\(3,4\) 之間。記兩個 bool 變數 \(l,r\) 表示當前這一行的 \(1,2 / 3,4\) 是否被 \(2 \times 2\) 矩形覆蓋,方便進行答案計算。

接下來分類討論:

  • \(a_i = 0\),不管它,跳過。
  • \(l = 1\)\(a_i \le 2\),此時這一行已經被覆蓋完,不用再操作。
  • \(3 \le a_i \le 4\) 時:
    • \(l = 1\)\(r = 1\),只需要在沒被覆蓋的那一邊放上一個 \(2 \times 2\) 的矩形即可,並將 \(l,r\) 都取反。
    • 否則一定是用操作二將這行全覆蓋。為什麼?因為不這樣寫過不了樣例根據上面的推論,在當前行放 \(2 \times 2\) 是與用兩個操作二等價的,還不如不用 \(2 \times 2\) 的矩陣,而是給下一行更多選擇機會,反正最劣也是再用一次操作二,更優的情況可能是 \(i + 1\) 行放 \(2 \times 2\) 省下一些步驟。
  • \(1 \le a_i \le 2\),放一個 \(2 \times 2\) 在左邊,並 \(l \gets 1,r \gets 0\) 即可。

code

#include<bits/stdc++.h>
#define ll long long
#define pb push_back
using namespace std;
const int N = 2e5 + 5;
int a[N];	
int n;
void solve(){
	cin >> n;
	for(int i = 1;i <= n;++ i) cin >> a[i];
	int ans = 0;
	bool l = 0,r = 0;
	for(int i = 1;i <= n;++ i){
		if(a[i] == 0 || (l && a[i] <= 2)){
			l = r = 0;
			continue;
		}
		if(a[i] > 4){
			l = r = 0;
			++ ans;
			continue; 
		}
		if(l || r){
			++ ans;
			swap(l,r);
			continue;
		}
		if(a[i] > 2){
			++ ans;
			l = r = 0;
			continue;
		}
		++ ans;
		l = 1;r = 0;
	}
	cout << ans << endl;
}
int main(){
	int _;
	cin >> _;
	while(_ --) solve();
	return 0;
}
/*
1
4
3 2 1 0
*/

相關文章