用C++實現:完美的代價

問題描述
  迴文串,是一種特殊的字符串,它從左往右讀和從右往左讀是同樣的。小龍龍認爲迴文串纔是完美的。如今給你一個串,它不必定是迴文的,請你計算最少的交換次數使得該串變成一個完美的迴文串。
  交換的定義是:交換兩個相鄰的字符
  例如mamad
  第一次交換 ad : mamda
  第二次交換 md : madma
  第三次交換 ma : madam (迴文!完美!)
輸入格式
  第一行是一個整數N,表示接下來的字符串的長度(N <= 8000)
  第二行是一個字符串,長度爲N.只包含小寫字母
輸出格式
  若是可能,輸出最少的交換次數。
  不然輸出Impossible
樣例輸入
5
mamad
樣例輸出
3
 
思路:先判斷這個字符串是否能夠組成一個迴文字符串,而後按照每個字母出現的次數爲偶數仍是奇數進行討論。每一次都是從第一個字母開始日後進行檢測,要是遇到了出現次數爲1的字母,先不要動它,等到其餘的字母都排完了,再直接將其放到字符串的中間便可;若是全部的字母出現次數都爲偶數個,那麼從字符串的最後開始往前檢測,直到遇到和當前字母相同的字母,再進行位置交換。
 
  1 #include<iostream>
  2 using namespace std;
  3 
  4 class huiwen
  5 {
  6 public:
  7     int get_n()
  8     {
  9         cin>>n;
 10         return n;
 11     }
 12     void get_putin()
 13     {
 14         cin>>putin;
 15     }
 16     void exchange()
 17     {
 18         for(int i=0;i<n;i++)
 19         {
 20             num[putin[i]-'a']++;
 21         }
 22         for(int i=0;i<26;i++)
 23         {
 24             if(num[i]%2!=0)
 25             {
 26                 t++;
 27             }
 28         }
 29         if(t>=2)  //要是有兩個或兩個以上的字母出現次數爲奇數,那麼這個字符串不可能爲迴文字符串
 30         {
 31             cout<<"Impossible";
 32             return;
 33         }
 34         else if(t==0)    //說明全部字母的出現次數都是偶數
 35         {
 36             for(int i=0;i<n/2-1;i++)
 37             {
 38                 flag=-1;
 39                 for(int j=n-a-1;j>i;j--)
 40                 {
 41                     if(putin[i]==putin[j])
 42                     {
 43                         flag=j;
 44                         break;
 45                     }
 46                 }
 47                 char temp=putin[flag];
 48                 for(int m=flag;m<n-1-a;m++)
 49                 {
 50                     putin[m]=putin[m+1];
 51                 }
 52                 putin[n-1-a]=temp;
 53                 time=time+(n-1-a-flag);   //計算移動次數
 54                 a++;
 55             }
 56         }
 57         else if(t==1)
 58         {
 59             for(int i=0;i<=n/2;i++)
 60             {
 61                 flag=-1;
 62                 for(int j=n-a-1;j>i;j--)
 63                 {
 64                     if(putin[i]==putin[j])
 65                     {
 66                         flag=j;
 67                         break;
 68                     }
 69                 }
 70                 if(flag==-1)   //遇到出現次數爲1次的字母了
 71                 {
 72                     time=time+(n/2-i);
 73                 }
 74                 else
 75                 {
 76                     char temp=putin[flag];
 77                     for (int m = flag; m < n - 1 - a; m++)
 78                     {
 79                         putin[m] = putin[m + 1];
 80                     }
 81                     putin[n - 1 - a] = temp;
 82                     time = time + (n - 1 - a - flag);   //計算移動次數
 83                     a++;
 84                 }
 85             }
 86         }
 87         cout<<time;
 88         return;
 89     }
 90 private:
 91     int n;    //輸入字符串所含字母個數
 92     char putin[8001];   //輸入字符串
 93     int num[26]={0};   //一共有26個字母,判斷每個字母的出現次數
 94     int t=0;   //整個字符串裏面有多少個出現次數爲奇數的字母
 95     int a=0;   //表示已經處理到第a個字母
 96     int flag;  //用flag來記錄後一半字符串匹配的最近的字母下標
 97     int time=0;  //用來計算移動字母的次數
 98 };
 99 
100 int main(void)
101 {
102     huiwen string;
103     string.get_n();
104     string.get_putin();
105     string.exchange();
106     return 0;
107 }

注意:題目中的交換的意思和通常的交換意思不同,這裏只能挨個地進行交換,而通常所說的交換是直接將兩個字符進行對調,因此計算交換次數的時候不能只算一次。ios

相關文章
相關標籤/搜索