Online JudgeProblem SetAuthorsOnline ContestsUser
Web Board
Home Page
F.A.Qs
Statistical Charts
Problems
Submit Problem
Online Status
Prob.ID:
Register
Update your info
Authors ranklist
Current Contest
Past Contests
Scheduled Contests
Award Contest
User ID:
Password:
  Register

我的解法

Posted by cavatina2016 at 2020-10-28 11:23:15 on Problem 1196 and last updated at 2020-10-28 15:06:21
先实现这个功能:求任意前缀的word个数。比如求所有前缀为AB的词个数。过程如下:

设这个前缀最大字符是ch。那么所有小于ch且没在前缀中出现的的字符在网格中的位置是受到限制的,可以对这些字符的位置进行暴力枚举。对大于ch的字符,它们的位置是不受到限制的,可以进行动态规划。

举个例子:
$$$$$
$###O
###OO
#OOOO
OOOOO

$是前缀,#是小于等于ch且未在前缀中出现的字符,O是大于ch的字符。求前缀是$$$的所有词个数,可以先对#进行暴力枚举,然后对O进行动态规划(容易看出,$+#总是分布于左上角,O总是分布于右下角,这为动态规划提供了可能)。

这个功能实现后,实现word与序号之间的转换就简单了。代码如下:


#include <stdio.h>
#include <cstring>


char prefix[26];
int len;
bool alphastates[26];
char grid[5][5];
int gridlens[5];
bool states[6 * 6 * 6 * 6 * 6];
int results[6 * 6 * 6 * 6 * 6];
char word[26];
int seq;


int calc(int s)
{
	if (states[s]) return results[s];

	int ss[5];
	for (int i = 0, s2 = s; i < 5; ++i) {
		ss[5 - 1 - i] = s2 % 6;
		s2 /= 6;
	}

	bool ok = true;
	for (int i = 0; i < 5; ++i) {
		if (ss[i] != 5) {
			ok = false;
			break;
		}
	}

	int res = 0;
	if (ok) {
		res = 1;
	}
	else {
		for (int i = 0; i < 5; ++i) {
			if (ss[i] < 5 && (i == 0 || ss[i] < ss[i - 1])) {
				ss[i]++;

				int s2 = 0;
				for (int j = 0; j < 5; ++j) {
					s2 *= 6;
					s2 += ss[j];
				}
				res += calc(s2);

				ss[i]--;
			}
		}
	}

	results[s] = res;
	states[s] = true;
	return res;
}


int calc(int idx, int maxidx)
{
	if (idx >= maxidx) {
		int s2 = 0;
		for (int j = 0; j < 5; ++j) {
			s2 *= 6;
			s2 += gridlens[j];
		}
		return calc(s2);
	}

	if (alphastates[idx]) {
		return calc(idx + 1, maxidx);
	}

	char ch = (char)('A' + idx);

	int res = 0;
	for (int i = 0; i < 5; ++i) {
		if (gridlens[i] >= 5 || i > 0 && gridlens[i] >= gridlens[i - 1]) continue;
		if (gridlens[i] > 0 && ch <= grid[i][gridlens[i] - 1]) {
			continue;
		}
		if (i > 0 && ch <= grid[i - 1][gridlens[i]]) {
			continue;
		}

		grid[i][gridlens[i]++] = ch;
		res += calc(idx + 1, maxidx);
		gridlens[i]--;
	}
	return res;
}


int calc()
{
	if (len == 0) {
		return calc(0);
	}

	char maxch = 0;
	memset(alphastates, 0, sizeof(alphastates));
	memset(gridlens, 0, sizeof(gridlens));

	for (int i = 0; i < 5; ++i) {
		for (int j = 0; j < 5; ++j) {
			int idx = i * 5 + j;
			if (idx >= len) break;

			char ch = prefix[idx];
			if (j > 0 && ch <= grid[i][j - 1]) {
				return 0;
			}
			if (i > 0 && ch <= grid[i - 1][j]) {
				return 0;
			}
			if (alphastates[ch - 'A']) return 0;

			alphastates[ch - 'A'] = true;
			grid[i][j] = ch;
			gridlens[i]++;

			if ((ch - 'A') > maxch) maxch = ch - 'A';
		}
	}

	return calc(0, maxch);
}


int word2seq()
{
	seq = 0;
	for (len = 1; len <= 25; ++len) {
		for (prefix[len - 1] = 'A'; prefix[len - 1] < word[len - 1]; ++prefix[len - 1]) {
			seq += calc();
		}
	}
	return seq;
}


void seq2word()
{
	for (len = 1; len <= 25; ++len) {
		for (prefix[len - 1] = 'A'; prefix[len - 1] < 'Z'; ++prefix[len - 1]) {
			int ret = calc();
			if (seq < ret) break;
			seq -= ret;
		}
	}
	for (int i = 0; i < 25; ++i) {
		word[i] = prefix[i];
	}
	word[25] = 0;
}


int main()
{
	memset(states, 0, sizeof(states));

	char buf[10];
	scanf_s("%s", buf, 10);

	if (buf[0] == 'W') {
		scanf_s("%s", word, 26);
		word2seq();
		printf("%d\n", seq + 1);
	}
	else {
		scanf_s("%d", &seq);
		seq--;
		seq2word();
		printf("%s\n", word);
	}
    return 0;
}


Followed by:

Post your reply here:
User ID:
Password:
Title:

Content:

Home Page   Go Back  To top


All Rights Reserved 2003-2013 Ying Fuchen,Xu Pengcheng,Xie Di
Any problem, Please Contact Administrator