[Swust OJ 648]--简单字典(数位dp)
题目链接:http://acm.swust.edu.cn/problem/0648/
Time limit(ms): 1000 Memory limit(kb): 65535
有这样一本字典,它每个单词一页,单词没有相同字母。
就像这样:
a 1
b 2
.
.
z 26
ab 27
.
.
az 51
ba 52
bc 53
.
.
就像这样:
a 1
b 2
.
.
z 26
ab 27
.
.
az 51
ba 52
bc 53
.
.
Description
多组测试数据,每行是一个串长最大为10由小写字母组成的单词。
以EOF结束。
以EOF结束。
Input
输出这个单词在这本字典的第几页
Output
1
2
3
4
|
a
az
abc
aa
|
Sample Input
1
2
3
4
|
1
51
677
ERROR
|
Sample Output
解题思路:这道题我们把它看做一个26进制的数位dp就可以了,就查找当前数前面有多少个数就是了,
值得注意的是这里可以有多个前导零0001,0003等(if (!fzero&&istrue&(1 << i)) continue;),
当一但出现非零数字后,后面的数字就不能再出现零(istrue | (1 << i))
关于数位dp不会的可以戳戳这里:http://www.cnblogs.com/zyxStar/p/4563830.html
代码如下:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 /*******************数位dp*************************/ 2 #include <iostream> 3 #include <cstring> 4 using namespace std; 5 6 int n, bit[11], judge[27], flag; 7 char s[11]; 8 9 int dfs(int pos, int istrue, bool limit, bool fzero){ 10 if (pos < 0) return 1; 11 int last = limit ? bit[pos] : 26; 12 int ret = 0; 13 for (int i = fzero ? 0 : 1; i <= last; i++){ 14 //允许多个前导零 15 if (!fzero&&istrue&(1 << i)) continue; 16 ret += dfs(pos - 1, istrue | (1 << i), limit&&i == last, fzero&&!i); 17 } 18 return ret; 19 } 20 21 int main(){ 22 while (cin >> s){ 23 n = strlen(s); 24 flag = 0; 25 memset(judge, 0, sizeof(judge)); 26 for (int i = n; i >= 1; i--){ 27 bit[n - i] = s[i - 1] - 'a' + 1; 28 if (!judge[bit[n - i]]) judge[bit[n - i]] = 1; 29 else { 30 flag = 1; 31 break; 32 } 33 } 34 if (flag) cout << "ERROR\n"; 35 else cout << dfs(n - 1, 0, 1, 1) - 1 << endl; 36 } 37 return 0; 38 }
如果这是你所爱的,就不要让自己后悔~~~