Codeforces Round #396 (Div. 2)C. Mahmoud and a Message(dp)

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

题意:给你一组小写字母组成的字符串,和26个数字,分别对应26位小写字母能够存在的字符串的最大长度。

   要求:①:求出最多的划分方案

      ②:求出分配方案中,最长的子串长度

      ③:求出分配方案中,最少分成的子串数

思路:关于①:设置dp[i],dp[i]表示在第i个字符后面有一个横杠的方案数,从第i个往前枚举前一个横杠的位置j。

举个例子,有子串abc,当横杠断在a处,有一种方案,dp[1]=1;当横杠断在b处时,i=2,j=2表示分出子串“b”时方案数,此时dp[2]+=dp[1]=1;

i=2,j=1时表示分出子串“ab”,此时dp[2]+=dp[0]=1;那最后dp1[2]就等于2了;同理可以推出dp[3]=4。最后可以总结为当j~i段字符符合条件时,有dp[i]+=dp[j-1]+1.

②就不多说了,枚举过程中找出最长的子串就好了。

关于③,设置f[i],表示到i时的子串数,如果j~i段符合条件,那j~i就可以变为一个子串,f[i]可以变为f[j-1]+1;

#include<iostream>
#include<algorithm>
#include<string>
using namespace std;
const int MOD=1e9+7;
const int inf=1<<30;
const int N=1e3+5;
int a[30],len;
int dp[N],f[N];
string st;
//每个小写字母都有一个数字a[i];表示这个字母能够存在于长度不超过a[i]的字符串内;
bool judge(int l,int r){
    int lim=r-l+1;
    for(int i=l;i<=r;i++){
        if(a[st[i]-‘a‘]<lim)
            return false;
    }
    return true;
}

int main(){
    int n,MAX=0;
    cin>>n>>st;
    st=" "+st;
    for(int i=0;i<26;i++){
        cin>>a[i];
    }
    //初始化
    dp[0]=1;
    f[0]=0;
    for(int i=1;i<=n;i++){
        f[i]=inf;
        for(int j=i;j>=1;j--){//j~i这一段字符串
            if(judge(j,i)){
                MAX=max(MAX,i-j+1);
                //printf("%d %d %d %d\n",i,j,dp1[i],dp1[j-1]);
                dp[i]=(dp[i]+dp[j-1])%MOD;//dp[i]表示在第i个字符后面有一个横杠的方案数,从第i个往前枚举前一个横杠的位置j
                f[i]=min(f[i],f[j-1]+1);//如果这一段合理,那么可以把j~i看成一个字串,那dp[i]的字串数也可以变形为dp[j-1]+1;
            }
        }
    }
    cout<<dp[n]<<endl;
    cout<<MAX<<endl;
    cout<<f[n]<<endl;
}
时间: 2024-10-13 15:39:07

Codeforces Round #396 (Div. 2)C. Mahmoud and a Message(dp)的相关文章

Codeforces Round #396(Div. 2) A. Mahmoud and Longest Uncommon Subsequence

[题意概述] 找两个字符串的最长不公共子串. [题目分析] 两个字符串的最长不公共子串就应该是其中一个字符串本身,那么判断两个字符串是否相等,如果相等,那么肯定没有公共子串,输出"-1".否则就是两个字符串中长的最长的长度. [AC] 1 #include<bits/stdc++.h> 2 using namespace std; 3 int main() { 4 char str1[100005],str2[100005]; 5 scanf("%s%s"

Codeforces Round #267 (Div. 2) C. George and Job(DP)补题

Codeforces Round #267 (Div. 2) C. George and Job题目链接请点击~ The new ITone 6 has been released recently and George got really keen to buy it. Unfortunately, he didn't have enough money, so George was going to work as a programmer. Now he faced the follow

Codeforces Round #433 (Div. 1) D. Michael and Charging Stations(dp)

题目链接:Codeforces Round #433 (Div. 1) D. Michael and Charging Stations 题意: 一个人每天要加油,1种为1000,1种为2000,如果付全额,会得到10%的回扣放在卡上. 如果卡上有剩余的回扣,可以拿来抵现金.问n天最少需要花多少钱. 题解: 很直观的一个dp就是考虑dp[i][j],表示第i天卡上剩余回扣为j的最小花费. 将所有的数除以100后,j其实是小于40的,严格的说是小于30,官方题解有个证明. 因为卡上不可能积累很多的

Codeforces Round #419 (Div. 2) E. Karen and Supermarket(树形DP)

题目链接:Codeforces Round #419 (Div. 2) E. Karen and Supermarket 题意: 有n件物品,每个物品有一个价格,和一个使用优惠券的价格,不过这个优惠券有一个限制,必须要在第x个使用后才可以使用.现在有m的钱,问最多能买多少个物品. 题解: 每个优惠券都只与一个券有关,所以根据这个关系就可以构成一棵树. 考虑树形dp,dp[i][j][k(0|1)]表示第i个节点所构成的子树中买了j个物品,使用优惠券和不使用优惠券的最少钱. 转移方程看代码详细解释

Codeforces Round #396 (Div. 2) D题Mahmoud and a Dictionary(并查集)解题报告

Mahmoud wants to write a new dictionary that contains n words and relations between them. There are two types of relations: synonymy (i. e. the two words mean the same) and antonymy (i. e. the two words mean the opposite). From time to time he discov

Codeforces Round #396 (Div. 2) C题Mahmoud and a Message(dp)解题报告

Mahmoud wrote a message s of length n. He wants to send it as a birthday present to his friend Moaz who likes strings. He wrote it on a magical paper but he was surprised because some characters disappeared while writing the string. That's because th

Codeforces Round #435 (Div. 2) D. Mahmoud and Ehab and the binary string[二分]

题目:http://codeforces.com/problemset/problem/862/D 题意:交互题,询问15次以内Hamming distance,输出一个二进制串里任意一个0或1的位置 题解:极简单的二分,从最后一位先判断一个,然后二分 根据上次和本次的距离差是否等于二分长度判断在左端还是右端有需要寻找的值寻找另一个. 1 #define _CRT_SECURE_NO_DEPRECATE 2 #pragma comment(linker, "/STACK:102400000,10

Codeforces Round #396 (Div. 2)

AB都是大水题. C题,题意稍微有点晦涩.但是还是一个比较简单的dp(虽然我不是独立的做出来的= =).感觉我dp掌握的不是很好啊:看到这题突然想起前几天碰到的一题:不考虑顺序的整数划分问题.C题代码如下: 1 #include <stdio.h> 2 #include <algorithm> 3 #include <string.h> 4 #include <iostream> 5 #include <string> 6 using names

Codeforces Round #435 (Div. 2) E. Mahmoud and Ehab and the function(预处理+二分)

题目链接:点我点我 题意:公式:,给出n个数,从a[1]到a[n],和m个数(b数组),然后从b数组里挑出连续的n个数(也就m-n+1中选择),按公式计算,使得f最小, 还有q次对a数组的操作(某个区间增加值,减少值),求出最小值. 题解:显然对a数组的处理非常简单,一开始确定一定值,然后update的时候,判断一下奇偶性质就可以直接加了(前一项正后一项一定是负的,可以抵消). 然后就是b数组的处理了,一开始没处理好,一直在这边卡超时.先把b数组一项一项正负不同的加进去,然后再进行处理,得到c数