题意:每次能执行相邻的字符交换,求让其字符串成为一个回文串要用到的最少的交换次数

思路:如何一个字符串中存在俩个以上的奇数字符的话,那么肯定是构不成回文串的,因为遇到奇数字符我们的处理方法是将其放在中间位置;

那么在其余的情况下,均为可以构成回文串的字符串,我们要想找到最少的操作次数,无非是不要重复的交换。

那么我们从字符串的开头位置开始,到(l+1)/2,这个位置,这是回文串的一半!然后我们要给其配对找另一半。

那么我们要从字符串的末位,开始搜寻到 i (即为对半个字符串遍历的当前位置),因为我们这样子做的话,就是外部排序是好的,就是字符串两边一直是好的,是回文的,然后就这样子一直往内,然后每交换一次,计数加一就行了

AC详细见代码

#include<bits/stdc++.h>

using namespace std;

map<char,int> st;
int tot=0;

int main(){
	int l;
	cin>>l;
	string s;
	cin>>s;
	for(int i=0;i<l;i++){
		st[s[i]]++;//统计各个字符的个数
	}
	map<char,int>::iterator  it;//auto蓝桥杯官网不能用
	for(it = st.begin();it!=st.end();it++){
		if(it->second % 2 == 1){
			tot++;
		} 
	}
	if(tot>=2){//两个以上的奇数字符就不能组成字符串
		cout<<"Impossible"<<endl;
	}
	else{
		int ans = 0;//计数
		int res = l;//长度
			for(int i=0;i<(l+1)/2;i++){//半个字符串遍历
				int j;
				for(j=res-1;j>i;j--){//寻找另一半
					if(s[i] == s[j]){
						while(j<res-1){//放在对的地方
							swap(s[j],s[j+1]);
							j++;
							ans++;
						}
						res--;//找到了下次就缩短查找长度
						break;
					}
				}
				if(i==j)//说明是奇数串!
				 ans += abs((l-1)/2 - i);//不知道单个字符在左还是右,所以用绝对值。
			  }
			  cout<<ans<<endl;
			}
	return 0;
}