首页 > 代码库 > uva10716Evil Straw Warts Live(贪心)

uva10716Evil Straw Warts Live(贪心)

题目: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;
}