洛谷 SP13105 【MUTDNA - DNA】
来发记忆化搜索的题解
先想搜索思路,先是肯定从后往前搜,因为后面为A的,肯定不动,如果一个点为B,那么肯定要么反转前面全部,要么单独反转,最后到第一个点的时候,看为A还是B的,A的话\(return 0\),否则\(return 1\)。然后就可以记忆化,\(f[i][j]\)表示第\(j\)个点为\(i\)(0为A,B为1)时的最优解,最后输出就行。
代码:
#include <bits/stdc++.h>
using namespace std;
int n;
int f[2][1000010] , a[1000010];
void dfs(int now , int tot){ //tot为转化了几次
int x = a[now] ^ tot; //看经过tot次转化变成了什么
if(f[x][now] != 0x3fffff) return;
if(!x){
dfs(now - 1 , tot);
f[x][now] = f[a[now - 1] ^ tot][now - 1]; //更新
}else{
dfs(now - 1 , tot ^ 1);
f[x][now] = f[a[now - 1] ^ (tot ^ 1)][now - 1];
dfs(now - 1 , tot);
f[x][now] = min(f[x][now] , f[a[now - 1] ^ tot][now - 1]); //更新
f[x][now]++; //要旋转
}
}
int main(){
cin >> n;
for(int i = 1; i <= n; i++){
f[0][i] = f[1][i] = 0x3fffff; //初始化
char s;
cin >> s;
if(s == 'A') a[i] = 0; //转化为0,1
else a[i] = 1;
}
f[0][1] = 0 , f[1][1] = 1; //边界
dfs(n , 0);
cout << f[a[n]][n]; //输出
return 0;
}
/*
12
AAABBBAAABBB
*/