蓝桥杯练习 BASIC-19 完美的代价

题目链接:http://lx.lanqiao.cn/problem.page?gpid=T60

基础练习 完美的代价
时间限制:1.0s 内存限制:512.0MB

问题描述
  回文串,是一种特殊的字符串,它从左往右读和从右往左读是一样的。小龙龙认为回文串才是完美的。现在给你一个串,它不一定是回文的,请你计算最少的交换次数使得该串变成一个完美的回文串。
  交换的定义是:交换两个相邻的字符
  例如mamad
  第一次交换 ad : mamda
  第二次交换 md : madma
  第三次交换 ma : madam (回文!完美!)
输入格式
  第一行是一个整数N,表示接下来的字符串的长度(N <= 8000)
  第二行是一个字符串,长度为N.只包含小写字母
输出格式
  如果可能,输出最少的交换次数。
  否则输出Impossible
样例输入
5
mamad
样例输出
3

思路

先特判不可能变成回文串的情况。

如果能变成回文串:(n为奇数且落单字符个数为1 或者 n为偶数且没有落单字符)
模拟, 一个指针 i 从左往右遍历,设 i 的对称位置为 k ,每次相当于先固定 i ,设一个指针 p 从右往左遍历(从 k 到 i+1)找与a[i]相同的字符。

找到时停止,此时与a[i]相同的字符的位置为p,把a[p]一直向右交换到a[k],这样就能使 a[i]=a[k];

但如果找不到与a[i]相同的字符,说明a[i]是落单的,这时需要把a[i]和a[i+1]交换一次,再找与新的a[i]相同的字符的位置,这时就一定能找到与新的a[i]配对的字符了(因为n为奇数才能有落单字符且落单字符个数为1,原a[i]是落单字符,则原a[i+1]一定不是落单字符)。

AC代码

#include <bits/stdc++.h>
using namespace std;
int n,p,k,ans,flag,vis[30];
char a[8010];
bool judge()
{
    int cnt=0;
    for(int i=1;i<=26;i++)
    {
        if(vis[i]%2==1)cnt++;//落单的个数为cnt(不是成对出现的)
        if(n%2==1&&cnt>1)return 1;
        if(n%2==0&&cnt>0)return 1;
    }
    return 0;

}
int main()
{
    ios::sync_with_stdio(false);
    cin>>n>>a+1;
    for(int i=1;i<=n;i++)
        vis[a[i]-'a'+1]++;
    if(judge())printf("Impossible\n");
    else
    {
        for(int i=1;i<=n/2;i++)
        {
            k=n+1-i;//k为对称位置
            if(a[k]!=a[i])
            {
                flag=0;
                for(p=k-1;p>i;p--)//p用来找与a[i]相同的字符的位置,从后往前找
                    if(a[p]==a[i]){flag=1;break;}
                if(flag==0)//找不到与a[i]相同的字符,说明a[i]落单了,把它与a[i+1]交换
                {
                    swap(a[i],a[i+1]);
                    ans++;
                    i--;//交换后再从新的a[i]开始循环,回退一次,把i--
                    continue;
                }
                for(;p<k;p++)//把a[p]与相邻的后一个字符a[p+1]交换,一直交换到i的对称位置k
                {
                    swap(a[p],a[p+1]);
                    ans++;
                }
            }
        }
        printf("%d\n",ans);
    }
    return 0;
}

附赠测试数据:

输入
97
eugygmammdetxltuvttfhwliqdmbflrlgirrnfejwcwjrhleelnqduvbnardaanseedkkyowzkzgknksokgdzxgznfecwrubw
输出
990

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

nefu-ljw

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值