| ||||||||||
| Online Judge | Problem Set | Authors | Online Contests | User | ||||||
|---|---|---|---|---|---|---|---|---|---|---|
| Web Board Home Page F.A.Qs Statistical Charts | Current Contest Past Contests Scheduled Contests Award Contest | |||||||||
我的解法先实现这个功能:求任意前缀的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: |
All Rights Reserved 2003-2013 Ying Fuchen,Xu Pengcheng,Xie Di
Any problem, Please Contact Administrator