【poj1850】 Code 数位dp+记忆化搜索

时间:2021-11-26 04:07:57

题目大意:给你一个字符串,问你这个字符串的rank,如果这个字符串不合法,请直接输出0。(一个合法的字符串是对于∀i,有c[i]<c[i+1])

字符串s的rank的计算方式:以字符串长度作为第一关键字,字符串大小作为第二关键字,将该字符串集排序,若从小到达数到的第k个字符串为s,则s的rank为k。

此题由于数据范围非常小(strlen(c)≤10),感觉暴力应该是可以AC的,不过我还是打了个数位dp。

此题直接记忆化搜索统计答案即可。不过要注意输入一个字符串时判断该字符串是否在该字符集内(我就未判这个结果翻车了....)

 #include<iostream>
#include<cstdio>
#include<cstring>
#define M 10
#define L long long
using namespace std;
L f[M][]={};
char c[M]={}; int num[M]={};
L dfs(int n,int m,int op){
if(!op&&f[n][m]!=-) return f[n][m];
if(n==) return ;
if(!op){
f[n][m]=;
for(int i=m+;i<=;i++) f[n][m]+=dfs(n-,i,op);
return f[n][m];
}else{
L sum=;
for(int i=m+;i<num[n];i++) sum+=dfs(n-,i,);
return sum+dfs(n-,num[n],op);
}
}
int main(){
scanf("%s",c+);
int n=strlen(c+);
for(int i=;i<=n;i++){
num[i]=c[n-i+]-'a'+;
if(c[i-]>=c[i]) {printf("0\n"); return ;}
}
memset(f,-,sizeof(f));
L sum=;
for(int nn=;nn<n;nn++){
for(int i=;i<=;i++)
sum+=dfs(nn-,i,);
}
for(int i=;i<num[n];i++)
sum+=dfs(n-,i,);
sum+=dfs(n-,num[n],);
printf("%lld\n",sum);
}