Codeforces Round #396 (Div. 2) C. Mahmoud and a Message DP
题意:
给你一个字符串;
然后让你把这个字符串进行分割;形成若干个小的字符串;
字母都有一个数字V[i];表示这个字母能够存在于长度不超过v[i]的字符串内;
问你有多少种分法,这些分法中,最长的一部分有多长,分成的部分最少的有多少份
题解:
dp[i][j]表示i位置向前组成长度j的一部分的方案数
所有的方案就是dp[i][1~1000],最长的去max就行,最少有多少份,再取个dp
#include<bits/stdc++.h> using namespace std; #pragma comment(linker, "/STACK:102400000,102400000") #define ls i<<1 #define rs ls | 1 #define mid ((ll+rr)>>1) #define pii pair<LL,int> #define MP make_pair typedef long long LL; const long long INF = 1e18; const double Pi = acos(-1.0); const int N = 1e3+10, mod = 1e9+7, inf = 2e9; int dp[N][N],v[N],sum[N],n,mi[N][N],ans=1,dp2[N]; char a[N]; int main() { scanf("%d%s",&n,a+1); for(int i = 0; i < 26; ++i) scanf("%d",&v[i]); sum[0] = 1; int mx = 0; for(int i = 1; i <= n; ++i) { mi[i][i] = v[a[i] - 'a']; for(int j = i+1; j <= n; ++j) { mi[i][j] = min(mi[i][j-1],v[a[j] - 'a']); } } for(int i = 1; i <= n; ++i) { dp[i][1] = sum[i-1]; sum[i] = sum[i-1]; dp2[i] = dp2[i-1] + 1; for(int j = 2; j <= i; ++j) { int tmp; if(mi[i-j+1][i] < j) tmp = 0; else tmp = 1; if(tmp) ans = max(ans,j); dp[i][j] = (1LL*tmp*sum[i-j]); sum[i] += dp[i][j]; sum[i] %= mod; if(tmp) dp2[i] = min(dp2[i-j]+1,dp2[i]); } } printf("%d\n%d\n%d\n",sum[n],ans,dp2[n]); return 0; }