题意:求最少的步骤使得原串变为回文串,贪心的做法很容易想到:每次都找离两端距离和最近的一对字符,然后分别移到两端就行了
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int MAXN = 8005;
char str[MAXN];
int vis[MAXN];
void swap(int &a,int &b)
{
int t = a;
a = b;
b = t;
}
bool isok()
{
memset(vis,0,sizeof(vis));
for (int i = 0; str[i]; i++)
vis[str[i] - 'a']++;
int sum = 0;
for (int i = 0; i < 26; i++)
if (vis[i] % 2)
{
sum++;
if (sum > 1)
return false;
}
return true;
}
int solve()
{
int len = strlen(str),sum = 0;
int left = 0,right = len - 1;
while (left < right)
{
int first = left,last = right,Max = MAXN *2;
memset(vis,0,sizeof(vis));
for (int i = left; i < right; i++)
{
if (!vis[i])
{
vis[i] = true;
int lastOccur = i,j;
for (j = i + 1; j <= right; j++)
if (str[j] == str[i])
{
vis[j] = true; // 中间的就更不可能是这个字符的最短了
lastOccur = j;
}
if (i - left + right - lastOccur < Max)
{
first = i,last = lastOccur;
Max = i - left + right - lastOccur;
}
}
}
for (int i = first; i > left; i--)
{
swap(str[i],str[i-1]);
sum++;
}
for (int i = last; i < right; i++)
{
swap(str[i],str[i+1]);
sum++;
}
left++,right--;
}
return sum;
}
int main()
{
int t;
scanf("%d",&t);
while (t--)
{
scanf("%s",str);
if (isok())
printf("%d\n",solve());
else printf("Impossible\n");
}
return 0;
}