贪心—完美的代价
问题描述
回文串,是一种特殊的字符串,它从左往右读和从右往左读是一样的。小龙龙认为回文串才是完美的。现在给你一个串,它不一定是回文的,请你计算最少的交换次数使得该串变成一个完美的回文串。
交换的定义是:交换两个相邻的字符
例如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;
}
这道题大概就是酱紫了,本人萌新一枚,欢迎大家与我交流哦~~