题解:AT_abc442_f [ABC442F] Diagonal Separation 2
我们考虑修改完的地图一定如下,红色代表白色。
就是一个倒着的阶梯状分割线,分割线左边是白色,右边是黑色。
我们考虑动态规划,设
我们拆解一下代价,发现可以分成两部分。一部分是使前
先考虑后一部分,因为这是一个倒阶梯状,我们设第
然后考虑前一部分,这个相对简单一点,我们只需要把第
代码如下。
#include<bits/stdc++.h>
using namespace std;
#define _for(i,a,b) for(int i = (a) ; i <= (b) ; i ++)
#define for_(i,a,b) for(int i = (a) ; i >= (b) ; i --)
#define ls k << 1
#define rs k << 1 | 1
const int inf = 1e9;
int n,ans = inf;
const int maxn = 5e3 + 10;
int dp[maxn][maxn];
int a[maxn][maxn];
int sum[maxn][maxn];
int min_dp[maxn];
int get_pay(int i,int j){
int tmp1 = sum[i][j] - sum[i - 1][j];//前j个黑点数量
int tmp2 = sum[i][n] - sum[i - 1][n] - tmp1;//后n-j个黑点数量
int tmp3 = (n - j) - tmp2;//后n-j个白点数量
return tmp1 + tmp3;
}
int main(){
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
memset(dp,0x3f,sizeof dp);
cin >> n;
_for(i , 0 , n) dp[0][i] = 0;
_for(i , 1 , n){
string s;
cin >> s;
_for(j , 1 , n) {
if(s[j - 1] == '#') a[i][j] = 1;
}
}
_for(i , 1 , n){
_for(j , 1 , n) {
sum[i][j] = sum[i - 1][j] + sum[i][j - 1] - sum[i - 1][j - 1] + a[i][j];
}
}
_for(i , 1 , n){
_for(j , 0 , n){
int tmp = get_pay(i,j);
if(i == 1) dp[i][j] = tmp;
else dp[i][j] = min_dp[j] + tmp;
}
min_dp[n] = dp[i][n];
for_(j , n - 1 , 0) min_dp[j] = min(dp[i][j],min_dp[j + 1]);
}
cout << min_dp[0];
return 0;
}