1. 程式人生 > >藍橋杯 基礎訓練 完美的代價(轉)

藍橋杯 基礎訓練 完美的代價(轉)

  基礎練習 完美的代價   時間限制:1.0s   記憶體限制:512.0MB 問題描述   迴文串,是一種特殊的字串,它從左往右讀和從右往左讀是一樣的。小龍龍認為迴文串才是完美的。現在給你一個串,它不一定是迴文的,請你計算最少的交換次數使得該串變成一個完美的迴文串。
  交換的定義是:交換兩個相鄰的字元
  例如mamad
  第一次交換 ad : mamda
  第二次交換 md : madma
  第三次交換 ma : madam (迴文!完美!) 輸入格式   第一行是一個整數N,表示接下來的字串的長度(N <= 8000)
  第二行是一個字串,長度為N.只包含小寫字母 輸出格式   如果可能,輸出最少的交換次數。
  否則輸出Impossible 樣例輸入 5
mamad 樣例輸出 3

分析:

貪心思想,從左向右遍歷,對於當前字元,從最右邊向左遍歷,找到與當前字元相同的,把它移動到正確位置,累加步數。

如果字串長度為偶數,只要有一個無法配對的字元,就不能變成迴文串,若為奇數,只要出現兩個無法配對的字元,也不能。

程式碼:

[cpp] view plaincopyprint?在CODE上檢視程式碼片派生到我的程式碼片
  1. #include <iostream>
  2. #include <cstdio>
  3. #include <algorithm>
  4. #include <cstring>
  5. #include <cctype>
  6. #define For1(i, a, b) for(int i = a; i <= b; i++)
  7. #define For2(i, a, b) for(int i = a; i >= b; i--)
  8. usingnamespace std;  
  9. int main()  
  10. {  
  11.     //freopen("in.txt", "r", stdin);
  12.     char ch[8010];  
  13.     int n, sum = 0, ok = 1, c = -1;  
  14.     scanf("%d%s", &n, ch);  
  15.     int j = n - 1;  
  16.     For1(i, 0, j-1){        //從左向右依次判斷
  17.         For2(k, j, i){      //從最右邊查詢,看有無與當前字元相同的
  18.             if(k == i){     //沒有找到與ch[i]相同的字元
  19.                 if(n % 2 == 0 || c != -1){      
    //若n為偶數或ch[i]不是唯一無法匹配的字元
  20.                     ok = 0;  
  21.                     break;  
  22.                 }  
  23.                 c = 1;              //n為奇數,ch[i]為第一個無法匹配的字元
  24.                 sum += n / 2 - i;       //將它移到中間所需步數
  25.                 break;  
  26.             }  
  27.             if(ch[k] == ch[i]){         //找到相同的
  28.                 For1(t, k, j - 1) ch[t] = ch[t + 1];        //往後移到對稱位置
  29.                 sum += j - k;  
  30.                 j--;  
  31.                 break;  
  32.             }  
  33.         }  
  34.         if(!ok) break;  
  35.     }  
  36.     if(!ok) printf("Impossible\n");  
  37.     else printf("%d\n", sum);  
  38.     return 0;  
  39. }