蓝桥杯练习系统—基础练习 完美的代价

第一部分:题目

问题描述
  回文串,是一种特殊的字符串,它从左往右读和从右往左读是一样的。小龙龙认为回文串才是完美的。现在给你一个串,它不一定是回文的,请你计算最少的交换次数使得该串变成一个完美的回文串。
  交换的定义是:交换两个相邻的字符
  例如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;
}

 

posted @ 2016-05-17 20:54  喝醉的香锅锅  阅读(2101)  评论(2编辑  收藏  举报