藍橋杯 基礎練習 BASIC-19 完美的代價


基礎練習 完美的代價  
時間限制:1.0s   內存限制:512.0MB
問題描述
  回文串,是一種特殊的字符串,它從左往右讀和從右往左讀是一樣的。小龍龍認為回文串才是完美的。現在給你一個串,它不一定是回文的,請你計算最少的交換次數使得該串變成一個完美的回文串。
  交換的定義是:交換兩個相鄰的字符
  例如mamad
  第一次交換 ad : mamda
  第二次交換 md : madma
  第三次交換 ma : madam (回文!完美!)
輸入格式
  第一行是一個整數N,表示接下來的字符串的長度(N <= 8000)
  第二行是一個字符串,長度為N.只包含小寫字母
輸出格式
  如果可能,輸出最少的交換次數。
  否則輸出Impossible
樣例輸入
5
mamad
樣例輸出
3
 
題目解析:
(1)Impossible 的兩種情況:
  • n為奇數時,如果已經有一個字符出現的次數為奇數,還找到了一個字符出現的次數為奇數,那么就不能構成回文串;
  • n為偶數時,只要找到有一個字符出現的次數為奇數,那么就不能構成回文串。
 (2)題目中要求輸出最小的交換次數,那么怎樣才能保證交換次數最小呢?
  如果 n 為偶數,那么從第一字符開始,從后往前找第一個和它相同的字符,如果找了,就將找到的字符交換到最后一個位置,在下一次遍歷時,就可以不用管剛才已經交換好的那來兩個字符;下一次從第二個字符開始,從倒數第二個字符開始遍歷,執行和上述相同的操作;
  如果 n 為奇數,在字符串的某一個位置找到了那個出現次數為奇數的字符,我們不必將次字符現在就交換到中間位置,而是先計算它到中間位置需要交換的次數,然后累加到 cnt 中,將剩下的字符都交換到對稱后,再交換這個字符即可。
  試着想一想,如果第一個字符就為出現次數為奇數的字符,那么將它交換到中間位置,接下來交換其他字符時,每次的交換次數都會多一次。這其實是一種普遍的規律。
 
示例代碼:
 1 #include<iostream>
 2 using namespace std;
 3 
 4 int main()
 5 {
 6     int n;
 7     cin >> n;
 8     string s;    
 9     cin >> s;
10     
11     int end = n - 1;    //字符串最后一個字符 
12     int cnt = 0;        //交換次數 
13     int oddNum = 0;        //判斷是否已經有一個單獨的奇個數的字符了
14     
15     for (int i = 0; i < end; i++)//從第一個字符到倒數第二個字符遍歷 
16     {
17         for (int j = end; j >= i; j--)//從最后一個開始,到第i個字符,尋找與s[i]相同的字符
18         {        
19             if (i == j)       //如果沒找到 
20             {
21                 if (n % 2 == 0 || oddNum == 1)  //不可能的兩種情況 
22                 {
23                     cout << "Impossible";
24                     return 0;
25                 }
26                 oddNum = 1;            //找到一個字符出現的次數為奇數 
27                 cnt += n / 2 - i;    //將次字符交換到中間位置的次數 
28             } 
29             else if (s[i] == s[j])    //如果找到了,將s[j]交換到s[end]位置 
30             {
31                 for (int k = j; k < end; k++)    //交換相鄰兩個位置的字符 
32                 {
33                     swap(s[k], s[k+1]);
34                     cnt++;
35                 }
36                 end--;                //末尾遞減 
37                 break;                //開始從i+1處重復操作 
38             }
39         }
40     }
41     
42     cout << cnt;
43     
44     return 0;
45 }

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM