[vijos1246]文科生的悲哀(二) 动态规划

背景

化学不及格的Matrix67无奈选择了文科。他必须硬着头皮艰难地进行着文科的学习。

描述

这学期的政治、历史和地理课本各有n章。每一科的教学必须按章节从前往后依次进行。若干章政治、若干章历史和若干章的地理内容可以合成一个教学阶段。年级计划将整个学期的内容分成若干个阶段进行教学。为了保证各科教学进度相同,年级规定每一个阶段包含的各科的章节数必须相同。一个阶段包含的章节越多,这个阶段所需要的课时也就越多。经过研究,假如某个阶段包含政史地各k章,则政治学习需要花费3^k天的课时,历史学习需要花费5^k天的课时,地理学习需要花费2^k天的课时,最后还需要4天的综合训练。一个阶段所花费的总时间是以上四项时间的和。

为了便于安排时间,学校希望每个阶段恰好需要若干周来完成。因此,划分出的每一个阶段所需要的天数都必须是7的整数倍(高三是没有星期六和星期天的)。

那么,这学期的课程最多可以划分成多少个阶段呢?你会想到,要想划分的阶段数最多,一个阶段完成一章的任务就行了(因为3^1+5^1+2^1+4=14是7的整数倍)。但问题没有这么简单。每个课本都可能有一些独立性较强的连续章节,它们具有很强的连续性,必须在一个阶段中完成。如果你已知所有不能划分在两个或两个以上的阶段中的连续章节,你还能计算出最多能安排多少个阶段吗?

格式

输入格式

第一行有两个用空格隔开的正整数n和m,分别表示各科课本的章节数和不可分割的连续章节的个数。

第二行到第m+1行,每行告诉了一个信息,该信息说明了哪一个课本的第几章到第几章必须一次性完成。同一科目给定的章节有可能重复或有重叠。

每一行信息分为两个部分。第一部分是“Politics:”、“History:”、“Geography:”三个字符串中的一个;第二部分是用“-”连接的两个数字x,y(1<=x<y<=n),表示该行第一部分所示的课本从第x章到第y章具有连续性。第二部分紧接在第一部分后面,没有任何符号分隔。

对于30%的数据,n,m<=10;
对于50%的数据,n,m<=1000;
对于100%的数据,n,m<=100 000。

输出格式

一个正整数,表示按照学校和年级的种种要求(见下)最多可以安排的阶段个数。

如果没有符合条件的安排方案,请输出-1。

注意:以下三个要求需要同时考虑。

1.每一个阶段包含的各科章数相同;
2.按时间函数计算出的各阶段所需天数必须是7的倍数;
3.给出的任一个连续章节都不能被分割开来。

样例1

样例输入1

8 3
Politics:1-2
History:5-6
Politics:1-4

Copy

样例输出1

3

Copy

限制

各个测试点1s

提示

样例说明:
最多可以安排三个阶段,具体方案如下:
第一阶段完成各科第1-6章的课程
第二阶段完成各科第7章的课程
第三阶段完成各科第8章的课程

Sample Input #2:
4 2
Geography:1-3
History:2-4

Sample Output #2:
-1

  这道题做了我一个上午………………orz

  一开始十分天真,注意到区间显然是可以合并之后(可以合并是因为一个阶段各科章节数一样)直接贪心了,能搞成一个阶段就搞成一个阶段……完美WA50

  事实上这个数据贪心就过不了:

18 3

Politics:3-6

Geography:7-12

History:13-18

  贪心结果是-1,正解是3。

  接着开始找题解但是却找不到,于是开始手糊正解。先是注意到,满足条件的章节数%6必然<3,且只有在区间交接处才有答案,其他地方都为-1;

  先合并区间并用pre[i]表示以i结尾的区间的起始位置。计算f[i]时只需用pre[i],pre[pre[i]],pre[pre[pre[i]]]……中满足条件的更新即可(因为f值并非递增所以不能在第一次更新后就退出)

  于是这样你就得到了在vijos上用时1700+s卡过的AC代码

  但这不行啊!显然是因为数据水评测机好才过的(xjoi上就T了……so sad……

  继续思考,最后发现假如i与某一个j=pre[pre[……pre[i]……]]的距离%6==0,那么显然在j之前对i满足条件的k必然对j也满足条件,所以f[j]就是j及之前的最大可更新值,所以更新后就可以直接跳出啦

  愉快的60+s AC~~~

评测结果及代码如下:

# 状态 耗时 内存占用
#1  Accepted  3ms 4.332MiB
#2  Accepted  3ms 4.25MiB
#3  Accepted  2ms 4.25MiB
#4  Accepted  2ms 2.367MiB
#5  Accepted  2ms 2.25MiB
#6  Accepted  4ms 4.25MiB
#7  Accepted  9ms 3.195MiB
#8  Accepted  10ms 3.457MiB
#9  Accepted  14ms 3.625MiB
#10  Accepted  11ms 4.871MiB
#include<cstdio>
#include<string>
#include<cstring>
using namespace std;
char s[200000];
int n,m,T[200],a[200000],b[200000],c[200000],f[200000],pre[200000],ans,d[200000];
int tdigit(int l,int r){
    int x=0;
    for(int i=l;i<=r;i++)
    x=x*10+s[i]-‘0‘;
    return x;
}
void done(int x);
int main(){
    scanf("%d%d",&n,&m);
    T[‘P‘]=9;T[‘H‘]=8;T[‘G‘]=10;
    for(int i=1;i<=m;i++){
        scanf("%s",s);    int x=0,y=0;
        for(int i=T[s[0]];i<strlen(s);i++)if(s[i]==‘-‘){x=tdigit(T[s[0]],i-1);y=tdigit(i+1,strlen(s)-1);break;}
        a[x]++;d[y]++;
    }
    int p=0,num=1,w=1;
    for(int i=1;i<=n;i++){
        p+=a[i];p==0?c[i]=0:c[i]=num;p-=d[i];
        if(p==0)num++;
    }
    for(int i=1;i<=n;i++)if(c[i]==0||c[i]!=c[i+1])pre[i]=w,w=i+1;
    for(int i=1;i<=n;i++)if(c[i]!=0&&c[i]==c[i+1])f[i]=0;else done(i);
    printf("%d",f[n]?f[n]:-1);
}
void done(int x){
    int j=pre[x];
    while(j){
        if(f[j-1]&&(x-j+1)%6<3){
            f[x]=max(f[x],f[j-1]+1);
            if((x-j+1)%6==0)break;
        }
        j=pre[j-1];
    }
    if(j==0&&f[x]==0&&(x-j)%6<3)f[x]=1;
}
时间: 2025-01-05 17:37:19

[vijos1246]文科生的悲哀(二) 动态规划的相关文章

[vijos1246]文科生的悲哀(二)

试题描述 化学不及格的Matrix67无奈选择了文科.他必须硬着头皮艰难地进行着文科的学习. 这学期的政治.历史和地理课本各有n章.每一科的教学必须按章节从前往后依次进行.若干章政治.若干章历史和若干章的地理内容可以合成一个教学阶段.年级计划将整个学期的内容分成若干个阶段进行教学.为了保证各科教学进度相同,年级规定每一个阶段包含的各科的章节数必须相同.一个阶段包含的章节越多,这个阶段所需要的课时也就越多.经过研究,假如某个阶段包含政史地各k章,则政治学习需要花费3^k天的课时,历史学习需要花费5

nyist oj 214 单调递增子序列(二) (动态规划经典)

单调递增子序列(二) 时间限制:1000 ms  |  内存限制:65535 KB 难度:4 描述 给定一整型数列{a1,a2...,an}(0<n<=100000),找出单调递增最长子序列,并求出其长度. 如:1 9 10 5 11 2 13的最长单调递增子序列是1 9 10 11 13,长度为5. 输入 有多组测试数据(<=7) 每组测试数据的第一行是一个整数n表示序列中共有n个整数,随后的下一行里有n个整数,表示数列中的所有元素.每个整形数中间用空格间隔开(0<n<=1

【斐波那契】vijos 1093 文科生的悲哀

背景 化学不及格的Matrix67无奈选择了文科.他必须硬着头皮准备一次又一次的文科考试. 描述 在这一学期一共有n次文科考试,考试科目有4种,分别为政治.历史.地理和综合.每 次考哪一科是不定的,因此在考试前Matrix67不知道应该去复习哪一科的功课.他希望能预测出下一次可能考的科目.于是,他收集到了以往的文科考试的 资料.从以往的考试中,他发现了这样几个规律: 1.如果这次考的是政治,那么下一次一定会考历史: 2.如果这次考的是综合,那么下一次一定会考地理: 3.如果这次考的是历史,那么下

算法学习——动态规划1

众所周知,在面试中最难,也是大公司最容易考的就是动态规划,所以今天打算开撕动态规划,之前只是对于单个的题目知道解法,不过时间一久就忘记了,今天开始要彻底的理解方法论再到实践,希望老天保佑能够一周搞定! 一.通过一个小例子了解方法论: 一个例子,如上图: 求从起点到终点的最短路径: 这是一道最基本的动态规划问题,如果不使用动态规划可以使用穷举进行求解,路径大概存在2的k次方.利用动态规划求解主要步骤: 1. 找出规划的初始状态:对此,找出第一个子问题的解从而可以在后面的内容中利用该解来作为后面状态

DP(动态规划)学习心得

动态规划学习心得 说实话吧,动态规划(DP)确实是一个比较难的知识点,对于初学者来说,是一个难过的坎(笔者的脸呢?开玩笑.).动态规划就是我从初学开始遇到的最神奇的解法,它不同于暴力搜索,也不同于一般的贪心,能够以出乎人意料的时间复杂度(近似于O(n^2))解决一些难题,算法远远优于一般的深搜(O(2^n)).不过,动态规划的思维性比较强,必须会设好状态,正确写出状态转移方程,并且能够准确判断有无最优子结构. 其实有点像贪心,但是它有局部最优解推导向整体最优解的过程,形象一点说,动态规划的“眼光

常见算法和例题

第3章  算法与程序设计模块 3.1  算    法 算法是对特定问题求解步骤的一种描述,它是指令的有限序列,其中每一条指令表示一个或多个操作. 常用的算法:列举了穷举搜索.递归.回溯.递推.模拟.分治.贪心.深度优先搜索.广度优先搜索等几种较为常用的算法,没有做过多的描述,一旦给出具体描述,容易使内容加深,产生严重学科取向的引导,符合教育部普通高中课程方案的特点,对于这些必需的方法和思想,关键不在于学生能不能,而在于教师是否想到,是否有过关注,引发学生对系统方法和思想的思考,重视建立编程思想,

大神刷题表

9月27日 后缀数组:[wikioi3160]最长公共子串 dp:NOIP2001统计单词个数 后缀自动机:[spoj1812]Longest Common Substring II [wikioi3160]最长公共子串 [spoj7258]Lexicographical Substring Search 扫描线+set:[poj2932]Coneology 扫描线+set+树上删边游戏:[FJOI2013]圆形游戏 结论:[bzoj3706][FJ2014集训]反色刷 最小环:[poj1734

TYVJ P1736 创意吃鱼法 Label:dp || 前缀和

题目描述 回到家中的猫猫把三桶鱼全部转移到了她那长方形大池子中,然后开始思考:到底要以何种方法吃鱼呢(猫猫就是这么可爱,吃鱼也要想好吃法 ^_*).她发现,把大池子视为01矩阵(0表示对应位置无鱼,1表示对应位置有鱼)有助于决定吃鱼策略. 在代表池子的01矩阵中,有很多的正方形子矩阵,如果某个正方形子矩阵的某条对角线上都有鱼,且此正方形子矩阵的其他地方无鱼,猫猫就可以从这个正方形子矩阵“对角线的一端”下口,只一吸,就能把对角线上的那一队鲜鱼吸入口中. 猫猫是个贪婪的家伙,所以她想一口吃掉尽量多的

1112个人赛,最长回文串常见算法讨论

ps.此贴大部分文字与代码来自网上,我只是取长补短整理了下 S=“c a b a”  那么  S' = “a b a c”, 这样的情况下 S和 S‘的最长公共子串是aba.没有错误. 但是当 S=“abacdfgdcaba”, 那么S’ = “abacdgfdcaba”. 这样S和S‘的最长公共子串是abacd.很明显abacd并不是S的最长回文子串,它甚至连回文都不是. 现在是不是都明白为什么最长回文子串不能转化成为最长公共子串问题了.当原串S中含有一个非回文的串的反序串的时候,最长公共子串