Codeforces 766C:Mahmoud and a Message(DP)

题目链接:http://codeforces.com/problemset/problem/766/C

 题意

有一个长度为n的字符串,第二行有26个数字,位置1~26对应为a~z的字母,数值表示该字母不能出现在长度超过该值的子串中。

  • 求有多少种划分该字符串的方法
  • 求该字符串划分成子串后最大的子串的长度
  • 求该字符串划分成满足要求的子串需要至少划分多少次

AC代码

#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <math.h>
#include <limits.h>
#include <map>
#include <stack>
#include <queue>
#include <vector>
#include <set>
#include <string>
#define ll long long
#define ms(a) memset(a,0,sizeof(a))
#define pi acos(-1.0)
#define INF 0x3f3f3f3f
const double E=exp(1);
const int maxn=1e6+10;
const int mod=1e9+7;
using namespace std;
char ch[maxn];
int c[maxn];
int a[maxn];
int dp[4][maxn];
int main(int argc, char const *argv[])
{
	ios::sync_with_stdio(false);
	int n;
	cin>>n;
	cin>>ch;
	for(int i=0;i<26;i++)
		cin>>a[i];
	for(int i=0;i<n;i++)
	{
		c[i]=ch[i]-'a';
	}
	dp[0][0]=1;//从位置0开始转移
	for(int i=1;i<=n;i++)
	{
		int res=INT_MAX/2;
		dp[1][i]=INT_MIN/2;
		dp[2][i]=INT_MAX/2;
		for(int j=i-1;j>=0;j--)
		{
			res=min(res,a[c[j]]);
			if(res<i-j)
				break;
			dp[0][i]=(dp[0][i]%mod+dp[0][j]%mod)%mod;
			dp[1][i]=max(dp[1][i],max(dp[1][j],i-j));
			dp[2][i]=min(dp[2][i],dp[2][j]+1);
		}
	}
	for(int i=0;i<3;i++)
		cout<<dp[i][n]<<endl;
	return 0;
}

 

posted @ 2018-08-17 14:59  友人-A  阅读(145)  评论(0编辑  收藏  举报