洛谷 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
*/
posted @ 2020-09-19 17:21  草鱼泡酒  阅读(76)  评论(0编辑  收藏  举报