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