藍橋杯練習系統—基礎練習 完美的代價


第一部分:題目

問題描述
  回文串,是一種特殊的字符串,它從左往右讀和從右往左讀是一樣的。小龍龍認為回文串才是完美的。現在給你一個串,它不一定是回文的,請你計算最少的交換次數使得該串變成一個完美的回文串。
  交換的定義是:交換兩個相鄰的字符
  例如mamad
  第一次交換 ad : mamda
  第二次交換 md : madma
  第三次交換 ma : madam (回文!完美!)
輸入格式
  第一行是一個整數N,表示接下來的字符串的長度(N <= 8000)
  第二行是一個字符串,長度為N.只包含小寫字母
輸出格式
  如果可能,輸出最少的交換次數。
  否則輸出Impossible
樣例輸入
5
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;
}

 


免責聲明!

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



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