[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 



Description
多组测试数据,每行是一个串长最大为10由小写字母组成的单词。 
以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
代码如下:
 
 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 }
View Code

 

你可能感兴趣的:(dp)