解题思路:
首先判断字符串能否构成回文,回文的本质是对称;
1、对于字符个数为偶数的字符串,所有的字母都是成偶数出现的,如果不是,直接输出Impossible
2、对于字符个数是奇数的字符串,有且仅有中间的一个字母数量为奇数(数量不一定为1),如果个数为奇数的字母数量出现一个以上,直接输出Impossible
接下来就是数交换的次数:
例如:aaabbccddee(以奇数为例,偶数类似)
总共有11个字符,且能构成回文,首先需要明白,若所有字母移动的次数最小,那么和就是最小的,先对整个构成回文的思路有一个初步的理解后,我们再来理解一下为什么和最小的原因;
在不考虑移动次数的情况下,我们如果要构成回文,那么只需以一边为标准即可,这里以左边为标准,改变右边的字母,看例子:
左边第一个字母为a,那么右边的最后一个字母也应为a,此时从右往左找,找到第一个与a相同的字母,移动到相应的位置,然后继续相同的步骤,这里先明白构成回文的基本方法,多出来的a会在考虑最小移动次数的情况下自然解决;
现在考虑最小移动次数,此时的回文标准是不固定的,有可能是以左边为标准,也有可能是以右边为标准,目的都是为了获得最小移动次数,此时,当我们以左边为标准寻找字母时,势必会找到一个相同的字母,且能知道移动的次数,然后把标准放到右边,同一个对称位置,如下图,从左边向右寻找,势必会找到一个相同的字
位置1 | 位置2(第一次标准) | 3 | 4 | …………………… | 4 | 3 | 位置2(第二次标准) | 位置1 |
母,且能知道需要移动的次数,那么我们需要移动的是次数较小的字母,对于那些非移动目标的字母,虽然被移动了,但都是向中间靠,所以对最终结果没有影响。现在来理解最小的原因,对于一个移动字母,直接从当前的位置向目标位置靠是移动次数最小的,在我们构成回文的过程中,以abcdefaccb为例(不用在意是否构成回文,只是为了做一个更加形象的解释),以左a为标准,abcdefaccb,从右往左找abcdefaccb<—,找到第一个a,abcdefaccb,移动次数为3,以右b为标准abcdefaccb,从左往右找,—>abcdefaccb,找到第一个b,abcdefaccb,移动次数为1,应该移动b,移动后为bacdefaccb,再来看a的情况,显然,移动次数变为2了,所以不影响结果。
参考代码:
while True:
try:
a=int(input())
b=input().strip()
b_temp=set(b)
suc=True
count=0
index=0
ans=0
for i in b_temp:
c=b.count(i)
if a%2==0 and c%2==1:
suc=False
break
if a%2==1 and c%2==1:
count+=1
if count>1:
suc=False
break
if suc:
for i in range(a//2):
for j in range(a-1-i,i,-1):
if b[i]==b[j]:
string1=b[0:j]
string2=b[j]
string3=b[j+1:a-i]
string4=b[a-i:a]
ans+=len(string3)
b = string1 + string3 + string2 + string4
break
if b[a-i-1]==b[a-j-1]:
string1=b[0:i]
string2=b[i:a-j-1]
string3=b[a-j-1]
string4=b[a-j:a]
ans+=len(string2)
b = string1 + string3 + string2 + string4
break
print(ans)
else:
print('Impossible')
except:
break
0.0分
2 人评分
C语言程序设计教程(第三版)课后习题12.1 (C语言代码)浏览:1026 |
矩阵转置 (C语言代码)浏览:1565 |
C语言训练-角谷猜想 (C语言代码)浏览:1767 |
矩阵乘法 (C++代码)浏览:1662 |
c primer plus 第十二章 12.1小节浏览:400 |
本人酷爱递归实现很多问题,这里也是浏览:632 |
【偶数求和】 (C语言代码)浏览:588 |
C语言程序设计教程(第三版)课后习题8.7 (C语言代码)浏览:609 |
C语言程序设计教程(第三版)课后习题10.1 (C语言代码)浏览:585 |
C语言程序设计教程(第三版)课后习题5.8 (C语言代码)浏览:1322 |