藍橋杯 基礎訓練 完美的代價(轉)
阿新 • • 發佈:2019-02-07
基礎練習 完美的代價
時間限制:1.0s 記憶體限制:512.0MB
問題描述
迴文串,是一種特殊的字串,它從左往右讀和從右往左讀是一樣的。小龍龍認為迴文串才是完美的。現在給你一個串,它不一定是迴文的,請你計算最少的交換次數使得該串變成一個完美的迴文串。
交換的定義是:交換兩個相鄰的字元
例如mamad
第一次交換 ad : mamda
第二次交換 md : madma
第三次交換 ma : madam (迴文!完美!) 輸入格式 第一行是一個整數N,表示接下來的字串的長度(N <= 8000)
第二行是一個字串,長度為N.只包含小寫字母 輸出格式 如果可能,輸出最少的交換次數。
否則輸出Impossible 樣例輸入 5
mamad 樣例輸出 3
交換的定義是:交換兩個相鄰的字元
例如mamad
第一次交換 ad : mamda
第二次交換 md : madma
第三次交換 ma : madam (迴文!完美!) 輸入格式 第一行是一個整數N,表示接下來的字串的長度(N <= 8000)
第二行是一個字串,長度為N.只包含小寫字母 輸出格式 如果可能,輸出最少的交換次數。
否則輸出Impossible 樣例輸入 5
mamad 樣例輸出 3
分析:
貪心思想,從左向右遍歷,對於當前字元,從最右邊向左遍歷,找到與當前字元相同的,把它移動到正確位置,累加步數。
如果字串長度為偶數,只要有一個無法配對的字元,就不能變成迴文串,若為奇數,只要出現兩個無法配對的字元,也不能。
程式碼:
[cpp] view plaincopyprint?- #include <iostream>
- #include <cstdio>
- #include <algorithm>
- #include <cstring>
- #include <cctype>
- #define For1(i, a, b) for(int i = a; i <= b; i++)
- #define For2(i, a, b) for(int i = a; i >= b; i--)
- usingnamespace std;
-
int main()
- {
- //freopen("in.txt", "r", stdin);
- char ch[8010];
- int n, sum = 0, ok = 1, c = -1;
- scanf("%d%s", &n, ch);
- int j = n - 1;
- For1(i, 0, j-1){ //從左向右依次判斷
- For2(k, j, i){ //從最右邊查詢,看有無與當前字元相同的
- if(k == i){ //沒有找到與ch[i]相同的字元
-
if(n % 2 == 0 || c != -1){
- ok = 0;
- break;
- }
- c = 1; //n為奇數,ch[i]為第一個無法匹配的字元
- sum += n / 2 - i; //將它移到中間所需步數
- break;
- }
- if(ch[k] == ch[i]){ //找到相同的
- For1(t, k, j - 1) ch[t] = ch[t + 1]; //往後移到對稱位置
- sum += j - k;
- j--;
- break;
- }
- }
- if(!ok) break;
- }
- if(!ok) printf("Impossible\n");
- else printf("%d\n", sum);
- return 0;
- }