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
*/

posted @   SunsetLake  阅读(37)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧

阅读目录(Content)

此页目录为空

-->
点击右上角即可分享
微信分享提示