POJ1850-Code 递推数学

题目链接:http://poj.org/problem?id=1850

题目大意:

  按照字典序对升序排列组成的字母进行编号,给出一个长度不超过10的串,求出它的编号是多少?如果无法进行编号则输出0。

题目分析:

  先判断字符串是不是升序的,如果不是升序的则不存在编号,直接输出0即可。

  满足升序要求的,则先根据长度len,把长度小于len的串整个处理一下,再对长度为len的递归求解。

  1.定义长度为i,以字母c开头的串的个数为f[i][c]。很容易看出来:f[i][c]=Σf[i-1][k](k=c+1-->'z'-i+2),解释一下k的取值,因为要求升序,所以以字母c开头的长度为i的串,相当于在长度为i-1的串前面插入一个c,可以插的串必然从c+1开始,直到‘z'-i+2。这个上界是为了满足长度的要求,长度为i-1的串最多只能以‘z'-i+2开头。

  2.在定义f[i][c]的时候,已经看出之中的递推关系了。那么对于长度为len的,按照串的顺序,依次处理如下:

  

for(int i='a';i<s[0];i++)//对首字母特殊处理
            ans+=f[len][i];

 for(int i=1;i<len;i++)
     for(int j=s[i-1]+1;j<s[i];j++)//对第i个字母处理。要注意是<s[i]。
                ans+=f[len-i][j];

ans++;//串本身的那个1.

  这样就求出解了。

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <string>
 5 using namespace std;
 6 int f[15]['z'+5];
 7 int main()
 8 {
 9     string s;
10     memset(f,0,sizeof(f));
11     for(int i='a';i<='z';i++)
12         f[1][i]=1;
13     for(int i=2;i<=10;i++)
14         for(int c='a';c<='z'-i+1;c++)
15             for(int k=c+1;k<='z'-i+2;k++)
16                 f[i][c]+=f[i-1][k];
17     while (cin>>s)
18     {
19         int len=s.size();
20         int ans=0;
21         bool ok=0;
22         for(int i=1;i<len;i++)
23             if(s[i]<=s[i-1])
24             {
25                 cout<<0<<endl;
26                 ok=1;
27                 break;
28             }
29         if(ok) continue;
30         for(int i=1;i<len;i++)
31             for(int c='a';c<='z'-i+1;c++)
32                 ans+=f[i][c];
33         for(int i='a';i<s[0];i++)
34             ans+=f[len][i];
35         for(int i=1;i<len;i++)
36             for(int j=s[i-1]+1;j<s[i];j++)
37                 ans+=f[len-i][j];
38         ans++;
39         cout<<ans<<endl;
40     }
41     return 0;
42 }
View Code
原文地址:https://www.cnblogs.com/xiaozhuyang/p/POJ1850-Code.html