蓝桥杯 完美的代价 【贪心】

版权声明:记笔记~~~ https://blog.csdn.net/weixin_42765557/article/details/87809592

问题描述

  回文串,是一种特殊的字符串,它从左往右读和从右往左读是一样的。小龙龙认为回文串才是完美的。现在给你一个串,它不一定是回文的,请你计算最少的交换次数使得该串变成一个完美的回文串。
  交换的定义是:交换两个相邻的字符
  例如mamad
  第一次交换 ad : mamda
  第二次交换 md : madma
  第三次交换 ma : madam (回文!完美!)

输入格式

  第一行是一个整数N,表示接下来的字符串的长度(N <= 8000)
  第二行是一个字符串,长度为N.只包含小写字母

输出格式

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

样例输入

5
mamad

样例输出

3

解题思路 

假如字符串所含字符个数为奇数,则有且只有一种字符的个数为奇数;为偶数则不能存在出现次数为奇数的字符。

调整交换:

从最左边到n/2枚举每个字符,从要处理的字符串的最右边开始往左找,找到相同的字符则交换到对应的位置,同时+交换次数。

如果找不到,则这个字符为处在字符串(奇数)最中间位置的字符,需要先假想不存在这个字符,当其他所有字符调整完之后再把它移到中间,+交换次数。

AC代码
 

#include <iostream>
using namespace std;
void Swap(char &t1,char &t2)
{
    char c = t2;
    t2 = t1;
    t1 = c;
}
int main()
{
    int n;
    char ch[8005];
    cin >> n >> ch;

    int ans=0;
    bool flag1=false,flag2=false;   // flag2用于确定出现次数为奇数的字符是否为0
    int r=n-1;
    for(int i=0;i<=n/2;i++) {
        for(int j=r;j>=i;j--) {  // 从右往左找与ch[i]相同的数
            if(i == j) {    // 没有找到与ch[i]相同的
                if(n%2 == 0 || flag2) {  // 一共偶数个字符 || 已经有出现次数为奇数的字符
                    cout << "Impossible\n";
                    flag1 = true;
                }
                else {
                    flag2 = true;
                    ans += n/2-i;   // 移到中间所需步数
                }
                break;
            }
            if(ch[i] == ch[j]) {      //找到相同的
                for(int k=j;k<r;k++)
                    Swap(ch[k],ch[k+1]);    //移到对应位置
                ans += (r-j);
                r--;    // 位置已经匹配好的不再参与之后的调整
                break;
            }
        }
        if(flag1)
            break;
    }
    if(!flag1)
        cout << ans << endl;

}
/*
9
ffdejjell
14
*/

猜你喜欢

转载自blog.csdn.net/weixin_42765557/article/details/87809592