POJ_1850_Code_DP,递推

蚊子是这个世界上最可恶的生物。

题意

将英文小写字母组成的字符串进行编号,满足每个字母都比它前面那个字母大的字符串可以被编号,所有字符串按长度第一要素,同长度字典序决定的方法排序,”a”编号为1,给一个字符串,判断其是否可以编号,如果可以,编号是多少。

输入输出

Input
The only line contains a word. There are some constraints:
• The word is maximum 10 letters length
• The English alphabet has 26 characters.

Output
The output will contain the code of the given word, or 0 if the word can not be codified.

分析

我的做法是先DP求出开头字母为i,长度为j+1的可编号字符串的数量,dp[i][j]=SUM(dp[k][j-1]), k>i
然后找所有比输入字符串小的串,长度比输入小的可以任意开头,然后长度相等的,对每一位,读取从’a’到字符串字符前一个作为i,长度为剩余字符串长度的dp值。

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
#define mxn 30
#define mxl 20
long long dp[mxn][mxl];
char a[mxl];
int len;
void set_dp(){
    memset(dp,0,sizeof(dp));
    for(int i=0;i<26;++i)   dp[i][0]=1;
    for(int j=1;j<10;++j)
        for(int i=0;i<26;++i)
            for(int k=i+1;k<26;++k)
                dp[i][j]+=dp[k][j-1];
}
bool ok(){
    for(int i=1;i<len;++i)  if(a[i]<=a[i-1])
        return false;
    return true;
}
int main(){
    set_dp();
    while(scanf("%s",a)!=EOF){
        len=strlen(a);
        if(!ok()){  puts("0");  continue;   }
        long long ans=0;
        for(int i=0;i<len-1;++i)
            for(int j=0;j<26;++j)
                ans+=dp[j][i];
        for(int i=0;i<len;++i)
            for(int j=(!i?0:a[i-1]-'a'+1);j<a[i]-'a';++j)
                ans+=dp[j][len-i-1];
        ++ans;
        cout<<ans<<endl;
    }
    return 0;
}
点赞