2020牛客国庆集训派对day1 H Ponk Warshall

https://ac.nowcoder.com/acm/contest/7817/H

给你a  g  t  c 让你两两交换最少的次数后,两个字符相等

如果  a--->g  而且  g---.a,就一步, a---->g,   g ---->t, t --- >a(长度为三的环)置换两步。

由于只有四个字符存在,可以枚举长度为2的环,3的环和4 的环,尽管字符又1e6的边,但是四个点,重合就边权了,具体看代码很好理解。

#include<iostream>
#include<cstring>
#include<queue>
#include<algorithm>
#include<vector>
using namespace std;
typedef long long ll;
const int maxn = 200+11;
int id[maxn];
string sn,cn;
int map[20][20];
int n;
ll ans = 0;
int main() {
	
	id['A'] = 1;
	id['G'] = 2;
	id['T'] = 3;
	id['C'] = 4;
	cin>>sn;
	cin>>cn;
	n = 4;
	for(int i=0; i<sn.length(); i++) {
		if(sn[i] == cn[i]) continue;
		map[id[sn[i]]][id[cn[i]]] ++;
	}
	ans = 0;
	//长度为2的环
	for(int i=1;i<=n;i++){
		for(int j=i+1;j<=n;j++){
			int ln = min(map[i][j],map[j][i]);
			ans += ln;
			map[i][j] -= ln;
			map[j][i] -= ln;
		}
	}
	//长度为3的环
	for(int i =1;i<=n;i++){
		for(int j=1;j<=n;j++){
			for(int k=1;k<=n;k++){
				if(i == j || k == j || i == k) continue;
				int ln = min(map[i][j],min(map[j][k],map[k][i]));
				ans += 2*ln;
				map[i][j] -= ln;
				map[j][k] -= ln;
				map[k][i] -= ln;
			}
		}
	} 
	//长度为4 的环
	for(int i =1;i<=n;i++){
		for(int j=1;j<=n;j++){
			for(int k=1;k<=n;k++){
				for(int s=1;s<=n;s++){
					if(i == j || j == k || k == s || j == k || s == k || s == j) continue;
					int a = min(map[i][j],map[j][k]);
					int b = min(map[k][s],map[s][i]);
					int ln = min(a,b);
					map[i][j] -= ln;
					map[j][k] -= ln;
					map[k][s] -= ln;
					map[s][i] -= ln;
					ans += 3*ln;
				} 
			}
		}
	}  
	printf("%lld
",ans);
	return 0;
}

  

寻找真正的热爱
原文地址:https://www.cnblogs.com/lesning/p/13758361.html