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; }