很遗憾这道题又不是完全自己想出来的。不过我要仔细的分析下我的思维过程,希望以后能逐渐优化。
开始看题,觉得要用贪心,感觉可以从中间往两边处理,但想不出严密的证明,其实后来才知道一开始就想错了。
还没完全想清楚的时候,我就开始写代码,写到一半发现问题,如果同一个字母在序列的同一边时,无论怎样移动这两个字母,移动之后序列的中心会改变,也就是另一半会多一个,到这里时我就进死胡同了,一直在想怎么解决这个问题,却一直没有好的办法。。。。就这样,我去看了题解。原来别人都是从两边往中间处理的。想了下,这样确实妙,因为每次移动之后,剩下中间的字母的移动范围都变小了,而且不用担心会改变序列的中心,于是开始重新写。可这里我又犯了个错,我没完全摆脱之前的思路,在遇到奇数长度序列时,先把该字母移动到中间,这样看似没问题,其实当之后处理时,如果还存在偶数个这个字母,可能就会移动这个中心字母到外围。。。这又时一处思维不严密。。
其实在遇到死胡同的时候,我就应该反思自己想得是不是有问题,甚至在一开始,我就应该意识到从两边处理会更好。一方面,自己舍不得已经写出来的代码,实际上我转换思路后没用多长时间就写出来了,而且代码也很短。好的意识,好的思路,绝对比打字的速度重要。。。。另一方面,还是尽量能不动脑经就不懂脑筋的习惯,或者叫潜意识。。。。。菜鸟啊,你什么时候能争点气
#include<cstdio>
#include<cstring>
#include<algorithm>
#define MAX 110
using namespace std;
char s[MAX],map[26];
int len,all;
void swap(char &i,int &j)
{
char t;
t=i,i=j,j=t;
}
void moveto(int a,int b)
{
int i,j;
if(a<b)
{
for(i=a;i<b;i++)
{
swap(s[i],s[i+1]);
all++;
}
}
else if(a>b)
{
for(i=a;i>b;i--)
{
swap(s[i],s[i-1]);
all++;
}
}
//printf("move%d %d to %d\n",all,a,b);
}
int main()
{
int t,i,j,js,which,a,b;
scanf("%d",&t);
while(t--)
{
memset(map,0,26);
scanf("%s",s);
len=strlen(s),js=0,all=0;
for(i=0;i<len;i++)
map[s[i]-'a']++;
for(i=0;i<26;i++)
if(map[i]%2==1)
{
js++;
which=i;
}
if(len%2==0&&js!=0||len%2==1&&js!=1)
{
printf("Impossible\n");
continue;
}
/*if(len%2==1)
{
if(s[len/2]!=which+1)
{
for(a=len/2-1,b=(len-1)/2+1;a>=0&&b<len;a--,b++)
{
if(s[a]==which+'a')
{
moveto(a,(len-1)/2);
break;
}
if(s[b]==which+'a')
{
moveto(b,(len-1)/2);
break;
}
}
}
}*/
for(a=0,b=len-1;a<=len/2&&b>=(len)/2&&a<=b;a++,b--)
{
if(s[a]==s[b])
continue;
for(i=b-1;s[i]!=s[a]&&i>=a;i--);
for(j=a+1;s[j]!=s[b]&&j<=b;j++);
if(i-a>b-j)
moveto(i,b);
else
moveto(j,a);
}
printf("%d\n",all);
}
return 0;
}
/*#include<cstdio>
#include<cstring>
#include<algorithm>
#define MAX 110
using namespace std;
char s[MAX],map[30];
int all,a,b,targeta,targetb,len;
void swap(char &i,int &j)
{
char t;
t=i,i=j,j=t;
}
void moveto(int a,int b)
{
int i,j;
if(a<b)
{
for(i=a;i<b;i++)
{
swap(s[i],s[i+1]);
all++;
}
}
else if(a>b)
{
for(i=a;i>b;i--)
{
swap(s[i],s[i-1]);
all++;
}
}
//printf("move%d %d to %d\n",all,a,b);
}
int find(int index)
{
int i,j,cur,temp,small=MAX;
for(cur=a-1;cur>=0;cur--)
{
if(s[cur]==s[index])
{
temp=index-cur-1+b-a-1;
if(temp<small)
{
small=temp;
if(index==a)
targeta=cur;
else
targetb=cur;
}
}
}
for(cur=b+1;cur<len;cur++)
{
if(s[cur]==s[index])
{
temp=cur-b;
if(temp<small)
{
small=temp;
if(index==a)
targeta=cur;
else
targetb=cur;
}
}
}
return small;
}
int main()
{
int t,i,j,js,which,smalla,smallb;
scanf("%d",&t);
while(t--)
{
scanf("%s",s);
len=strlen(s);
js=all=0;
memset(map,0,30);
for(i=0;i<len;i++)
map[s[i]-'a']++;
for(i=0;i<26;i++)
{
if(map[i]%2==1)
{
js++;
which=i;
}
}
if(len%2==0&&js!=0||len%2==1&&js!=1)
{
printf("Impossible\n");
continue;
}
if(len%2==1)
{
for(i=0;i<len;i++)
{
if(s[i]==which+'a')
{
moveto(i,(len-1)/2);
break;
}
}
}
//printf("teat");
for(a=len/2-1,b=(len-1)/2+1;a>0&&b<len-1;a--,b++)
{//printf("teat");
//printf("b %d %d all%d s%s\n",s[a],s[b],all,s);
if(s[a]==s[b])
continue;
smalla=find(a);
smallb=find(b);
printf("a%d %d\n",smalla,smallb);
if(smalla<smallb)
{
if(targeta<a)
{
moveto(targeta,a-1);
moveto(a,b-1);
}
else
moveto(targeta,b);
}
else
{
if(targetb>b)
{
moveto(targetb,b+1);
moveto(b,a+1);
}
else
moveto(targetb,a);
}
}
printf("%d\n",all);
}
return 0;
}*/