第一部分:題目
問題描述
回文串,是一種特殊的字符串,它從左往右讀和從右往左讀是一樣的。小龍龍認為回文串才是完美的。現在給你一個串,它不一定是回文的,請你計算最少的交換次數使得該串變成一個完美的回文串。
交換的定義是:交換兩個相鄰的字符
例如mamad
第一次交換 ad : mamda
第二次交換 md : madma
第三次交換 ma : madam (回文!完美!)
交換的定義是:交換兩個相鄰的字符
例如mamad
第一次交換 ad : mamda
第二次交換 md : madma
第三次交換 ma : madam (回文!完美!)
輸入格式
第一行是一個整數N,表示接下來的字符串的長度(N <= 8000)
第二行是一個字符串,長度為N.只包含小寫字母
第二行是一個字符串,長度為N.只包含小寫字母
輸出格式
如果可能,輸出最少的交換次數。
否則輸出Impossible
否則輸出Impossible
樣例輸入
5
mamad
mamad
樣例輸出
3
第二部分:我的思路
1,能否變成回文串:記錄每個小寫字母的個數,只要奇數的個數不超過1就可以。
2,最少交換次數:貪心:從兩端同時開始,不一樣的時候需要找到最近的替換:兩邊的都可以替換,只要交換次數最小也就是最近。
第三部分:代碼
#include<iostream> #include<stdio.h> using namespace std; int main() { int len; cin>>len; getchar();//接收cin的回車符 char s[8001]; int sum[27]={0};//用來記錄26個小寫字母的個數 gets(s); for(int i=0;i<len;i++) { sum[s[i]-'a'+1]++; } int t=0; //字母個數為奇數的總數超過1就不可能變成回文串。 for(int i=1;i<27;i++) { if(sum[i]%2!=0) { t++; } if(t>1) { break; } } if(t>1) { cout<<"Impossible"<<endl; } else { int count=0; int i,j; //從兩端同時開始,不一樣時用離左或右最近的替換:一個一個交換過來。 for(i=0,j=len-1;i<j;i++,j--) { if(s[i]!=s[j]) { int min=10000; int index; int flag=0; //可以替換左邊的 for(int l=i+1;l<j;l++) { if(s[l]==s[j]) { if(min>l-i) { min=l-i; index=l; break; } } } //可以替換右邊的 for(int l=j-1;l>i;l--) { if(s[l]==s[i]) { if(min>j-l) { min=j-l; index=l; flag=1; break; } } } count+=min; if(flag) { int t=s[index]; for(int k=index;k<j;k++) { s[k]=s[k+1]; } s[j]=t; } else { int t=s[index]; for(int k=index;k>i;k--) { s[k]=s[k-1]; } s[i]=t; } } } cout<<count<<endl; } return 0; }