藍橋杯練習——完美的代價

前言

傳送門,文章思路參考自柳神博客——https://blog.csdn.net/liuchuo/article/details/51990430

正文

問題描述

迴文串,是一種特殊的字符串,它從左往右讀和從右往左讀是一樣的。小龍龍認爲迴文串纔是完美的。現在給你一個串,它不一定是迴文的,請你計算最少的交換次數使得該串變成一個完美的迴文串。
交換的定義是:交換兩個相鄰的字符
例如mamad
第一次交換 ad : mamda
第二次交換 md : madma
第三次交換 ma : madam (迴文!完美!)

輸入格式

第一行是一個整數N,表示接下來的字符串的長度(N <= 8000)
第二行是一個字符串,長度爲N.只包含小寫字母

輸出格式

如果可能,輸出最少的交換次數。
否則輸出Impossible

樣例輸入

5
mamad

樣例輸出

3

AC代碼

/*
1.impossible的情況:如果有一個字符出現的次數是奇數次數,而且n是偶數,那麼不可能構成迴文
如果n是奇數,但是已經有一個字符出現的次數是奇數次數了,那麼如果又有一個字符是奇數次數,就不可能構成迴文。
2.如果n是奇數,計算中間那個字符交換的次數的時候,不需要模擬把這個數移動到中間去,因爲移動到中間的話假設有一對數都在左邊或者都在右邊,
那麼交換成迴文的時候就要經過中間,就會每次把cnt多加了1,而這個1是沒有必要的,因爲可以所有的迴文移動完了之後再把這個獨立的奇數移動過去,才能保證交換次數最少。
*/
#include<iostream>
#include<cstring>
using namespace std;
int main(){
	int n,cnt=0;//cnt表示交換次數 
	string str;
	cin>>n>>str;
	int left,right=n-1;
	bool isShow=false;//用於標記是否已經出現過奇數次數的字符 
	for(left=0;left<right;left++){
		for(int i=right;i>=left;i--){//從後往前遍歷,匹配相同的字符
			if(i==left){//說明字符str[left] 出現的次數爲奇數次 
				if(n%2==0||(n%2==1&&isShow==true)){//出現Impossible的兩種情況 
					cout<<"Impossible\n"; 
					return 0;
				}
				isShow=true; 
				cnt+=n/2-left;//把字符str[left]移動到最中間需要移動的次數 
			} else if(str[i]==str[left]){//找到兩個相同的字符 ,將str[i]移動到與str[left]對應的位置 ,也就是將str[i]移動到right指示的位置 
				for(int j=i;j<right;j++){//這裏進行交換,爲了使j+1<n,即j<n-1,故right=n-1  
					swap(str[j],str[j+1]);
					cnt++;
				} 
				right--; //此時right位置上已經是換好的str[i],因此right繼續往左走 
				break;
			} 
		}
	}
	cout<<cnt;
	return 0;
} 

後記

你強任你強

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章