uva 517 - Word(暴力+周期)

题目链接:uva 517 - Word


题目大意:给出一个字符串,以及8种变换方式,问说该字符串变换s次后的结果,注意字符串为环形,输出字典序最小的情况。


解题思路:因为字符串最长为15, 2^15<max(s), 所以一定会出现周期,暴力枚举周期。


#include <stdio.h>
#include <string.h>
#include <set>

using namespace std;

const int N = 20;

struct state {
	int k, v;
	friend bool operator < (const state& a, const state& b) {
		return a.k < b.k;
	}
};

int n, s, t[8];
set<state> rec;
char str[N];

void init() {
	rec.clear();
	char cha[N];

	scanf("%s", str);
	for (int i = 0; i < 8; i++) {
		scanf("%s", cha);
		int sum = 0;
		for (int j = 0; j < 3; j++) 
			sum = cha[j] - ‘a‘ + sum * 2;
		t[sum] = cha[3] - ‘a‘;
	}
	scanf("%d", &s);
}

int judge(char* a, char* b, int p, int& q) {
	int sum;
	for (int i = 0; i < n; i++) {
		sum = (a[i] - ‘a‘) * 4 + (a[(i+2)%n] - ‘a‘) * 2 + a[(i+3)%n] - ‘a‘;
		b[(i+2)%n] = t[sum] + ‘a‘;
	}
	b[n] = ‘\0‘;

	sum = 0;
	for (int i = 0; i < n; i++) sum = sum * 2 + b[i] - ‘a‘;
	state u;
	u.k = sum; u.v = p;

	set<state>::iterator it = rec.find(u);
	if (it != rec.end()) {
		q = it->v;
		return p - q;
	} else {
		rec.insert(u);
		return 0;
	}
}

void solve() {
	int cnt, q = 0;
	bool flag = false;
	char tmp[N];
	for (int i = 0; i < n; i++) q = q * 2 + str[i] - ‘a‘;
	state u; u.k = q; u.v = 0;
	rec.insert(u);

	for (int i = 1; i <= s; i++) {
		cnt = judge(str, tmp, i, q);
		if (cnt) {
			cnt = (s-q) % cnt;
			flag = true;
			break;
		}
		strcpy(str, tmp);
	}

	if (flag) {
		cnt += q;

		for (set<state>::iterator i = rec.begin(); i != rec.end(); i++) {
			if (i->v == cnt) {
				cnt = i->k; break;
			}
		}

		for (int i = n-1; i >= 0; i--) {
			tmp[i] = ‘a‘ + cnt % 2;
			cnt /= 2;
		}
	}

	char ans[N];
	strcpy(ans, tmp);
	strcpy(str, tmp);	

	for (int i = 0; i < n; i++) {
		tmp[0] = str[n-1];
		strncpy(tmp+1, str, n-1);
		if (strcmp(ans, tmp) > 0) strcpy(ans, tmp);
		strcpy(str, tmp);
	}
	printf("%s\n", ans);
}

int main() {
	while (scanf("%d%*c", &n) == 1) {
		init();
		solve();
	}
	return 0;
}


uva 517 - Word(暴力+周期)

上一篇:谷歌中一些十分有趣的特效现象


下一篇:UVa 644 立即可解码性