基础练习 完美的代价

问题描述
  回文串,是一种特殊的字符串,它从左往右读和从右往左读是一样的。小龙龙认为回文串才是完美的。现在给你一个串,它不一定是回文的,请你计算最少的交换次数使得该串变成一个完美的回文串。
  交换的定义是:交换两个相邻的字符
  例如mamad
  第一次交换 ad : mamda
  第二次交换 md : madma
  第三次交换 ma : madam (回文!完美!)
输入格式
  第一行是一个整数N,表示接下来的字符串的长度(N <= 8000)
  第二行是一个字符串,长度为N.只包含小写字母
输出格式
  如果可能,输出最少的交换次数。
  否则输出Impossible
样例输入
5
mamad
样例输出
3
 
思路:
1.如果是奇数串,如果出现两个字符都为奇数,则 printf("Impossible"); ;否则就进行从右向左遍历,寻找与字符串前端相同的字符,如果找到便 cnt 自增,要注意如果遇到了单个的字符先不要移动,放在最后等其他字符都回文了之后它自然会在中间,如果先把它移动到了中间则会导致其他字符移动的时候会多移动一次,所以我们只需要在加把它移动到中间的次数即可: cnt += length/2-i; 

2.如果是偶数串,如果遇到一个单个字符即为Impossible,因为偶数串有一个单个字符则必定有另一个单个字符;否则就进行从右向左遍历,寻找与字符串前端相同的字符,如果找到便 cnt 自增

 1 #include<stdio.h>
 2 
 3 char s[8001];
 4 int main()
 5 {
 6     int length,i,j,k;
 7 
 8     scanf("%d", &length);
 9     getchar();
10     for (i = 0; i < length; i++)
11     {
12         scanf("%c", &s[i]);
13     }
14 
15     int end = length - 1;
16     int cnt = 0;
17     int oddNum = 0;
18 
19     for (i = 0; i < end; i++)
20     {
21         for (j = end; j >= i; j--)
22         {
23             if (i == j)
24             {
25                 if (n % 2 == 0 || oddNum == 1)  //如果在偶数串中找到了单个的字符;如果第二次遇到单个字符
26                 {
27                     printf("Impossible");
28                     return 0;
29                 }
30                 oddNum = 1;
31                 cnt += n / 2 - i;
32             }
33             else if (s[i] == s[j])
34             {
35                 for (k = j; k < end; k++)
36                 {
37                     char t = s[k];
38                     s[k] = s[k + 1];
39                     s[k + 1] = t;
40                     cnt++;
41                 }
42                 end--; //末尾长度减一
43                 break;
44             }
45         }
46     }
47     printf("%d", cnt);
48     return 0;
49 }
原文地址:https://www.cnblogs.com/ZhengLijie/p/12692653.html