D
鸽.....
E
给一个2*n的网格,一些(至少一个)网格上面存在一个物品,当两个物品移动到同一个网格的时候变成一个
每次可以移动一个物品,求移动的最小次数
首先求出存在物品的列区间为[l, r]
显然存在,不会将物品移动到[l, r]之外
在[l, r]之间做dp
f[i][0]:表示从l列移动到第i列,并且停在了第一行
f[i][1]:表示从l列移动到第i列,并且停在了第二行
状态转移:根据第i列物品的状态以及第i-1停在了哪一行,很容易进行状态
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 2e6 + 10;
char a[N], b[N];
int f[N][2];
int n;
int main(){
int T; cin >> T;
while(T--){
scanf("%d", &n);
scanf("%s", a + 1);
scanf("%s", b + 1);
int l = 2e9, r = 0;
for(int i = 1; i <=n; i ++){
if(a[i] == '*' || b[i] == '*') l = min(l, i), r = max(r, i);
}
// 初始化
if(a[l] == '*' && b[l] == '*') f[l][0] = 1, f[l][1] = 1;
else if(a[l] == '*') f[l][0] = 0, f[l][1] = 1;
else if(b[l] == '*') f[l][0] = 1, f[l][1] = 0;
// 状态转移
for(int i = l + 1; i <= r; i ++){
if(a[i] == '*' && b[i] == '*'){
f[i][0] = min(f[i - 1][0] + 2, f[i - 1][1] + 2);
f[i][1] = min(f[i - 1][0] + 2, f[i - 1][1] + 2);
}
else if(a[i] == '*' && b[i] != '*'){
f[i][0] = min(f[i - 1][0] + 1, f[i - 1][1] + 2);
f[i][1] = min(f[i - 1][0] + 2, f[i - 1][1] + 2);
}
else if(a[i] != '*' && b[i] == '*'){
f[i][0] = min(f[i - 1][0] + 2, f[i - 1][1] + 2);
f[i][1] = min(f[i - 1][0] + 2, f[i - 1][1] + 1);
}
else{
f[i][0] = min(f[i - 1][0] + 1, f[i - 1][1] + 2);
f[i][1] = min(f[i - 1][1] + 1, f[i - 1][0] + 2);
}
}
cout << min(f[r][0], f[r][1]) << endl;
}
return 0;
}