• 蓝桥杯基础练习 完美的代价


    问题描述
      回文串,是一种特殊的字符串,它从左往右读和从右往左读是一样的。小龙龙认为回文串才是完美的。现在给你一个串,它不一定是回文的,请你计算最少的交换次数使得该串变成一个完美的回文串。
      交换的定义是:交换两个相邻的字符
      例如mamad
      第一次交换 ad : mamda
      第二次交换 md : madma
      第三次交换 ma : madam (回文!完美!)
    输入格式
      第一行是一个整数N,表示接下来的字符串的长度(N <= 8000)
      第二行是一个字符串,长度为N.只包含小写字母
    输出格式
      如果可能,输出最少的交换次数。
      否则输出Impossible
    样例输入
    5
    mamad
    样例输出
    3
    解题思路:
    求最少的交换次数,考虑用贪心算法,当一个字符不动,另一个字符移动到对称位置时移动步数最少。
    有字符个数为奇数和偶数两种情况:
    1. 字符个数为偶数,不能有不对称的字符。
    2. 字符个数为奇数,没有对称字符的字符只能有一个,设变量flag来标记是不是第一次不对称。

    另外需要注意:

      奇数情况下若找到不对称字符,不能先移动它,将移动至中间所需要的步数加入总步数即可,可以想象第一个字符为非对称字符的情况代入程序中,非对称字符移动到中间,使得第二个字符变成第一个字符,但是外循环已经跳过了第一个字符(如果要先移动非对称字符,则移动后需要从上一个位置重新计算)。

     
    #include <iostream>
    #include <cstdio>
    using namespace std;
    
    int main()
    {
        char str[8001];
        int n, end, j, k, cnt=0, flag=1;
        cin>>n;getchar();
        for(int i=0; i<n; i++)
            scanf("%c", &str[i]);
        end = n-1;    //end为最后一个字符下标 
        //从头开始遍历
        for(int i=0; i<end; i++)
        {
            //从末尾开始遍历
            for(j=end; j>=i; j--)
            {
                //找不到相同的字符 
                if(i == j)
                {
                    //判断不是第一次找不到匹配的字符 或 n为偶数
                    if(flag==0 || n%2==0)
                    {
                        //返回impossible
                        printf("Impossible
    ");
                        return 0;    
                    }
                    //是第一次找不到且n为奇数,则将flag变为0,计算应该移动多少位(n/2-j)但不要真的移动
                    /*
                    *不匹配的字符如果在数组的后半部分则当其他位置匹配时必然n/2==j,
                    *即不需要移动,如果在前半部分则需要移动n/2-j,当然减i也行(此时i==j) 
                    */
                    else 
                    {
                        flag = 0; 
                        cnt += n/2-i; 
                    }
                }
                //找到相同的字符
                else if(str[j] == str[i])
                {
                    //将该位置的字符与向后相邻的字符交换,直到end
                    for(k=j; k<end; k++)//注意不能连end也算入,k+1已经替换了end 
                    {
                        swap(str[k], str[k+1]);
                        cnt++;
                    }
                    //end向前移动一位(因为该位置已经对称) 
                    end--;
                    break;
                }
                
            }    
        }
        cout<<cnt<<endl; 
        
        return 0;
    }
    
    /*注:
    程序中的判断是否找到相同字符if... else if...位置不可交换,因为i==j时,
    必然str[i]==str[j],但是这是找不到的情况 
    */
  • 相关阅读:
    Java实现最大流量问题
    Java实现最大流量问题
    Java实现最大流量问题
    Java实现最大流量问题
    Java实现行列递增矩阵的查找
    Java实现行列递增矩阵的查找
    Java实现行列递增矩阵的查找
    Java实现行列递增矩阵的查找
    Java实现行列递增矩阵的查找
    通过QML Profiler分析程序性能问题
  • 原文地址:https://www.cnblogs.com/kamicoder/p/8535214.html
Copyright © 2020-2023  润新知