贪心—完美的代价(蓝桥杯练习系统)

贪心—完美的代价

问题描述

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

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

例如mamad

第一次交换 ad : mamda

第二次交换 md : madma

第三次交换 ma : madam (回文!完美!)
  
输入格式  
第一行是一个整数N,表示接下来的字符串的长度(N <= 8000)

第二行是一个字符串,长度为N.只包含小写字母输出格式  如果可能,输出最少的交换次数。

否则输出Impossible样例输入5
样例输入
5
mamad
样例输出
3

今天在蓝桥杯练习系统做了这样的一道有关字符串的题,这道题看起来还是比较常规的,但鉴于本人(很萌新),解题过程中犯了许多错误,于是蒟蒻觉得有必要还是记录一下写出这道题的过程。当然,这应该不是最优的方法吧哈哈,dalao请自行跳过。

代码如下

#include <iostream>
#include <vector>
#include <stdio.h>
#include <cmath>
using namespace std;
int main()
{
 vector<char> a;//使用容器存放数据,方便交换访问和删除数据
 string x;
 char pos;//为了记录(可通过交换形成回文串时的情况)出现字母为奇数的字母。
 int i,n,b[8001]={0},flag=0,f=0,head,tail,target=0,diff=1,s=0;
 cin>>n;
 a.clear();
 head=0;
 tail=n-1;
 cin>>x;//将字符串整体放入x
 for(i=0;i<n;i++)
 {
  a.push_back(x[i]);//字符串放入容器
  b[(x[i]-'a')]++;//记录a~z的字母依次出现的次数,为了判断该字符串可否变为回文串
 }
 if(n%2==0)//字符数为偶数时,判断字符串可否变为回文串(有更好的办法,不过当时是这样写的,凑合看吧@v@)
 {
  for(i=0;i<n;i++)
  {
   if(b[i]%2!=0)
   {
    flag=1;
    break;
   }
  }
 }
 if(n%2!=0)//字符数为偶数时,判断字符串可否变为回文串
 {
  for(i=0;i<26;i++)
  {
   if(b[i]%2!=0&&f==0)
   {
    f=1;
    pos=(i+'a');
    continue;
   }
   if(b[i]%2!=0)
   {
    flag=1;
    break;
   }
  }
 }
 while(flag==0&&head<n/2)
 {
  if(a[head]!=a[tail])
  {
   for(i=tail;i>head;i--)
   {
    if(a[i]==a[head])
    {
     target=i;
     diff=0;
     break;
     cout<<i<<" "<<head<<endl;
    }
   }
   if(diff==1)//这里很重要(小k就在这里进过坑),当找不到与其匹配的情况时,说明他应该放在正中间的情况。不过这里不要调整他,只是先记录下他到中间所需移动的次数,然后head跳过他,tail不动。
   {
    s+=abs((n/2)-head);
    head++;
    continue;
   }
   s+=abs(target-tail);
   if(tail+1>=n)
   a.push_back(a[target]);
   else
   a.insert(a.begin()+tail+1,a[target]);
   a.erase(a.begin()+target);
   diff=1;
  }
  head++;
  tail--;
 }
 if(flag==1)
 cout<<"Impossible"<<endl; //此情况不能形成回文串
 else 
 cout<<s<<endl;//输出结果
 return 0;
} 

这道题大概就是酱紫了,本人萌新一枚,欢迎大家与我交流哦~~

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值