CodeForces

来源:互联网 发布:刷游戏的软件 编辑:程序博客网 时间:2024/05/21 12:50

题意

给出一个字符串 和每个字符的限制数量ai 让我们随意的切割成多个字符串 使得每一个字符串中的特定字符所在的子串长度len<=ai
求一共有多少个符合题目要求的方案 求其中最长的一个串长度是多少 求其中最少能分成多少个串
长度最大为1000

分析

明显可以用搜索 不过复杂度指数级 计数问题
考虑dp
对于第i个字符 他可以考虑从i-ai+1开始往后到i分割字符 我们这里可以枚举分割的位置
然后记录下来 那么对于第i个字符 我们知道他前面所有字符的分割数量 就可以更新第i个字符的分割方案 假设用dp[i]表示从1到第i个字符的可行分配方案 那么dp[i] +=dp[j]其中合法情况之和 就可以计数出所有情况的可能

code

#include<iostream>#include<cstdio>#include<algorithm>#include<cstring>#include<string>using namespace std;const int mod = 1e9+7;char a[1010];int dp[1010],mmin[1010],mmax,res[26];bool judge(int pos,int l){        for(int i=pos-l+1;i<=pos;i++){                if(res[a[i]-'a']<l)return 0;        }        return 1;}int main(){    int n;    scanf("%d%s",&n,a+1);    for(int i=0;i<26;i++)scanf("%d",&res[i]);    dp[0]=1;    for(int i=1;i<=n;i++){                mmin[i] = mod;                for(int j=1;j<=i;j++){                        if(judge(i,j)){//如果符合条件 就把方案数转移到更长的字符下                                dp[i] = (dp[i]+dp[i-j])%mod;                                mmin[i] = min(mmin[i],mmin[i-j]+1);//两个dp变量 都要更新 这里就是要把段数一并更新                                 mmax = max(mmax,j);                        }                }    }    printf("%d\n%d\n%d\n",dp[n],mmax,mmin[n]);    return 0;}
原创粉丝点击