题目:uva10716Evil Straw Warts Live(贪心)
题目大意:给出一个字符串,问如何交换字母位置能够得到回文。这里求最少的交换次数。如果不能通过交换得到回文,输出Impossible。
交换只允许和相邻的字母进行交换。
解题思路:贪心策略:每次都是先将距离两边距离和最短的对称的字母移到到两边,这样这两个字母就对称了,且交换次数是最少的。然后就将这两个字母从字符串中移除。再用相同的方法接着判断剩下的字符串。直到剩余的字符串长度 <= 1就可以停止了。
代码:
#include <stdio.h> #include <string.h> #include <stdlib.h> const int N = 105; const int M = 26; char s[N]; int visit[N]; int solve () { memset (visit, 0, sizeof (visit)); int len = strlen(s); for (int i = 0; i < len; i++) visit[s[i] - 'a']++; int count = 0; for (int i = 0; i < M; i++) if (visit[i] % 2) count++; if ( (len % 2 && count == 1) || (len % 2 == 0 && !count)) { int l, r, min; count = 0; while (len > 1) { min = N; memset (visit, 0, sizeof (visit)); for (int i = 0; i < len; i++) { if (visit[i]) continue; visit[i] = 1; for (int j = len - 1; j >= 0; j--) { if (s[j] == s[i] && !visit[j]) { visit[j] = 1; if (len - abs (i - j) - 1 < min) { min = len - abs (i - j) - 1; l = i; r = j; } break; } } // printf ("%d\n", min); } count += min; // printf ("%d\n", min); // printf ("%d\n", count); // printf ("%d %d\n", l, r); if (l > r) { min = l; l = r; r = min; } for (int i = l; i < len - 1; i++) s[i] = s[i + 1]; for (int i = r - 1; i < len - 2; i++) s[i] = s[i + 1]; // s[len - 2] = '\0'; // printf ("%s\n", s); len -= 2; } return count; } return -1; } int main () { int t; int count; scanf ("%d", &t); while (t--) { scanf ("%s", s); count = solve(); if (count < 0) printf ("Impossible\n"); else printf ("%d\n", count); } return 0; }
uva10716Evil Straw Warts Live(贪心)
时间: 2024-10-25 20:04:54