[题解] CF1990D Grid Puzzle
Monke_FClBrI · · 题解
Links: [Codeforces] [Luogu]
题意
给定一个长为
- 选择图中一个
2\times 2 的子矩形染成白色; - 选择图中一行格子染成白色。
问让每个格子都变为白色至少需要多少次操作。每个测试点
思路
看到这题首先有个很简单的想法:如果有连续的两行黑格数都小于等于
然后我们思考会不会有方块叠成更多层,可以发现如果我们要在某个行上覆盖三个方块,那么显然这样只能覆盖至多
然后考虑用 DP 求解。设
- 第
i 行不填,那么要么是a_i=0 ,要么是a_i\le 2 且前一行填了1,2 列。 - 第
i 行填整行,那么要求前一行没有填方块(因为前一行填方块,本行填整行的方案总是不优于两行都填整行)。 - 第
i 行1,2 列填方块,如果a_i\le 2 ,那么可以i-1 行不填方块;如果a_i\le 4 那么可以i-1 行填3,4 列,第i 行插进去。 - 第
i 行3,4 列填方块,如果a_i\le 4 ,那么i-1 行填1,2 列,第i 行叠上去。
即转移如下:
转移到
代码
#include<bits/stdc++.h>
#define pb push_back
#define SZ(x) (int)((x).size())
using namespace std;
const int N=2e5+5,INF=1e9;
int _,n,a[N],f[N][3],ans;
signed main(){
ios::sync_with_stdio(false);cin.tie(0),cout.tie(0);
cin>>_;
while(_--){
cin>>n;for(int i=1;i<=n;i++)cin>>a[i],f[i][0]=f[i][1]=f[i][2]=INF;
if(n==1){cout<<!!a[1]<<'\n';continue;}
f[1][0]=!!a[1];if(a[1]<=2)f[1][1]=1;
for(int i=2;i<n;i++){
f[i][0]=f[i-1][0]+!!a[i];
if(a[i]<=2)f[i][0]=min(f[i][0],f[i-1][1]),f[i][1]=f[i-1][0]+1;
if(a[i]<=4)f[i][1]=min(f[i][1],f[i-1][2]+1),f[i][2]=f[i-1][1]+1;
}
ans=f[n-1][0]+!!a[n];if(a[n]<=2)ans=min(ans,f[n-1][1]);
cout<<ans<<'\n';
}
return 0;
}
(逃