zoukankan      html  css  js  c++  java
  • 贪心算法:完美的代价(蓝桥杯练习题)

    资源限制
    时间限制:1.0s   内存限制:512.0MB

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

    输入格式
      第一行是一个整数N,表示接下来的字符串的长度(N <= 8000)
      第二行是一个字符串,长度为N.只包含小写字母
    输出格式
      如果可能,输出最少的交换次数。
      否则输出Impossible

    样例输入
    5
    mamad
    样例输出
    3
     
    实现代码(c++)
     1 #include<iostream>
     2 using namespace std;
     3 
     4 int n=0;
     5 int num[30]={0};
     6 //思想:先检测字符是否可以形成回文数,再分单长度和偶长度进行操作,
     7 //对于一个字符串,从前到后扫描,若是次数出现为1次的,则先不动记下最后移动次数,
     8 //如果出现次数为偶数,则从该字符串的末尾去扫描,从尾部开始找到与当前字符相同的字符,再进行位置变换 
     9 int main(){
    10     char s[8001];
    11     int time=0; 
    12     cin>>n;
    13     cin>>s;
    14     
    15     for(int i=0;i<n;i++){
    16         num[(s[i]-'a')]++;
    17     } 
    18     int ff=0;
    19     for(int i=0;i<26;i++){
    20         if(num[i]%2!=0)    ff++;
    21     }
    22     if(ff>=2){        //表示字符串中有2个以上的单次数出现的字符 不符合 
    23         cout<<"Impossible";
    24         return 0;
    25     }
    26     
    27     if(ff==0){        //表示,没有单个次数出现的字符 不需要考虑最中间这项 
    28         int t=0;    //表示已经处理好开头t个元素
    29         for(int i=0;i<=n/2-1;i++){    //从头扫描到中间 
    30             int flag=-1;        //标志找到最近的匹配元素的下标 
    31             for(int j=n-1-t;j>i;j--){
    32                 if(s[i]==s[j]){
    33                     flag=j;        //保存下标 
    34                     break;
    35                 }
    36             } 
    37             
    38             //进行位置的移动
    39             char temp=s[flag];
    40             for(int m=flag;m<n-1-t;m++){
    41                 s[m]=s[m+1];
    42             }
    43             s[n-1-t]=temp;
    44             
    45             //计算元素移动的次数 
    46             time+=n-1-t-flag;
    47             
    48             t++;    //表明字符串完成一位字符的匹配而+1 
    49         } 
    50     }else if(ff==1){
    51         int t=0;    //表示已经处理好开头t个元素
    52         for(int i=0;i<=n/2;i++){
    53             int flag=-1;
    54             for(int j=n-1-t;j>i;j--){
    55                 if(s[i]==s[j]){
    56                     flag=j;        //保存下标 
    57                     break;
    58                 }
    59             } 
    60             
    61             if(flag==-1){        //表示碰见了单次数元素 
    62                 //先不移动,最后移动
    63                 time+=n/2-i; 
    64             }else{
    65                 //位置移动
    66                 char temp=s[flag];
    67                 for(int m=flag;m<n-1-t;m++){
    68                     s[m]=s[m+1];
    69                 }
    70                 s[n-1-t]=temp; 
    71                 
    72                 //次数
    73                 time+=n-1-t-flag;
    74                 
    75                 t++;
    76             }
    77         }
    78     }
    79     cout<<time;
    80     return 0;
    81 }
  • 相关阅读:
    Bzoj1101 [POI2007]Zap
    Bzoj2393 Cirno的完美算数教室
    UVa10891 Game of Sum
    Bzoj4128 Matrix
    类的组合
    继承
    属性查找与绑定方法
    类与对象
    面向对象程序设计——基础概念
    修改个人信息的程序
  • 原文地址:https://www.cnblogs.com/xwh-blogs/p/12466671.html
Copyright © 2011-2022 走看看