[蓝桥杯][基础练习VIP]完美的代价(暴力)

题目描述

回文串,是一种特殊的字符串,它从左往右读和从右往左读是一样的。小龙龙认为回文串才是完美的。现在给你一个串,它不一定是回文的,请你计算最少的交换次数使得该串变成一个完美的回文串。

交换的定义是:交换两个相邻的字符

例如mamad

第一次交换  ad  :  mamda

第二次交换  md  :  madma

第三次交换  ma  :  madam  (回文!完美!)
 

输入

第一行是一个整数N,表示接下来的字符串的长度(N  < =  8000) 

第二行是一个字符串,长度为N.只包含小写字母 

输出

如果可能,输出最少的交换次数。 

否则输出Impossible 

样例输入

5 
mamad 

样例输出

3

分析:本题求解交换次数的基本思路是首位配对,即将左边第一个字符与右边最后一个字符开始比较,如果相符,则各向右向左移动比较下一个字符。

                              

如果不符,则右边字符向左移动

                                

这样求得所有交换次数加起来即为最小的

其实在每次比较并且还没有找到相符的字符时还要看一下左右两个指针是否已经相遇,如果相遇,说明字符串里面没有与该字符相配的字符,这个时候就要考虑三种情况

1、若字符串的字符数是偶数个则一定不是回文串,输出Impossible结束

2、若字符串的字符数是奇数个,则这个字符可能要放到中间不与任何字符配对。先假定这种情况进行标记,并且统计这个字符到中间位置需要交换的次数。加到总交换次数中

3、若之前已经标记过一次假定中间有字符,又遇到一次字符无法匹配的那么这种情况也无法构成回文串了,输出Impossible结束

说明:这个题还有一个细节,就是输入时不知道为什么测试数据n后面包含两个回车所以输入时还要把这两个回车给读取掉,要不然对后边输入字符串有影响。(用scanf读取,用getchar()读取回车在评测时会有部分答案错误   >_<|||)

#include<stdio.h>
const int M=8e3+5;
char str[8005];
int i,j,k,l,n,t,sum,a;
char temp;
int main(){
    scanf("%d\n\n",&n);
    fgets(str,M,stdin);
    k=n-1;
    t=0;
    sum=0;
    for(i=0;i<=k;i++){
        for(j=k;j>=i;j--){
            if(j==i){ //首尾字母相遇,说明没有找到
                if(n%2==0||t==1)//如果是偶数个字符那么肯定不是回文串,还有一种情况就是
                                //虽然是奇数个字符,但之前已经有假设中间字符,这次又有
                                //无法匹配的字符,那么也肯定不是回文串
                {
                    printf("Impossible\n");
                    return 0;
                }
                t=1;//如果是奇数个字符,那么可以暂时假设这个无法匹配的字符为中间字符
                sum+=(n/2-i);//把这种假定情况需要交换的字符数量统计进去
            }
            else if(str[i]==str[j]){//找到相符字符
                for(l=j;l<k;l++)//从找到字符位置开始到之前位置开始交换,并统计交换次数
                {
                    temp = str[l];
                    str[l] = str[l+1];
                    str[l+1] = temp;
                    sum++;
                }
                k--;
                break;
            }
        }
        if(a==1)
            break;
    }
    printf("%d\n",sum);

}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值