CF1990D Grid Puzzle 题解
思路
首先有一个观察:对于 \(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
*/