NOI 2009A 诗人小G

诗人小G

【问题描述】

小G是一个出色的诗人,经常作诗自娱自乐。但是,他一直被一件事情所困扰,那就是诗的排版问题。

一首诗包含了若干个句子,对于一些连续的短句,可以将它们用空格隔开并放在一行中, 注意一行中可以放的句子数目是没有限制的。小G给每首诗定义了一个行标准长度(行的长度为一行中符号的总个数),他希望排版后每行的长度都和行标准长度相差不远。显然排版时,不应改变原有的句子顺序,并且小G不允许把一个句子分在两行或者更多的行内。在满足上面两个条件的情况下,小G对于排版中的每行定义了一个不协调度, 为这行的实际长度与行标准长度差值绝对值的P次方,而一个排版的不协调度为所有行不协调度的总和。

小G最近又作了几首诗,现在请你对这首诗进行排版,使得排版后的诗尽量协调(即不协调度尽量小),并把排版的结果告诉他。

【输入文件】

输入文件poet.in包含多组数据。

第一行包含一个整数T,表示诗的数量,接下来是T首诗,这里一首诗即为一组数据。每组数据的第一行包含三个由空格分隔的正整数NLP,其中N表示这首诗句子的数目,L表示这首诗的行标准长度,P的含义见问题描述。从第2行开始,每行为一个句子,句子由英文字母、数字、标点符号等符号组成(ASCII码33~127, 但不包含 ‘-’)。

【输出文件】

输出文件为poet.out。

对于每组数据,若最小的不协调度不超过1018,则第一行一个数表示不协调度,接下来若干行,表示你排版之后的诗。注意:在同一行的相邻两个句子之间需要用一个空格分开。如果有多个可行解,它们的不协调度都是最小值,则输出任意一个解均可。若最小的不协调度超过1018,则输出"Too hard to arrange"(不包含引号)。每组数据结束后输出"--------------------"(不包括引号),共20个"-","-"的ASCII码为45,请勿输出多余的空行或者空格。

【输入样例】

4

4 9 3

brysj,

hhrhl.

yqqlm,

gsycl.

4 9 2

brysj,

hhrhl.

yqqlm,

gsycl.

1 1005 6

poet

1 1004 6

poet

【输出样例】

108

brysj,

hhrhl.

yqqlm,

gsycl.

--------------------

32

brysj, hhrhl.

yqqlm, gsycl.

--------------------

Too hard to arrange

--------------------

1000000000000000000

poet

--------------------

【样例说明】

前两组输入数据中每行的实际长度均为6,后两组输入数据每行的实际长度均为4。一个排版方案中每行相邻两个句子之间的空格也算在这行的长度中(可参见样例中第二组数据)。每行末尾没有空格。

【评分方法】

本题设有部分分,当你的程序对于该测试点内每组数据计算得出的不协调度最小值都正确时,能得到本测试点70%的分数。在此情况下,若每组数据的排版方案都合法并且得出的不协调度都与输出的相等,则能得到本测试点剩下30%的分数。注意,输出格式错误可能会导致本测试点不得分。

【数据规模和约定】

总共10个测试点,数据范围满足:

测试点

T

N

L

P

1

≤10

≤18

≤100

≤5

2

≤10

≤2000

≤60000

≤10

3

≤10

≤2000

≤60000

≤10

4

≤5

≤100000

≤200

≤10

5

≤5

≤100000

≤200

≤10

6

≤5

≤100000

≤3000000

2

7

≤5

≤100000

≤3000000

2

8

≤5

≤100000

≤3000000

≤10

9

≤5

≤100000

≤3000000

≤10

10

≤5

≤100000

≤3000000

≤10

所有测试点中均满足句子长度不超过30。

直接dp,30分做法详细分析:

状态转移方程:

f[i] = min(f[j] + |s[i] - s[j] + i - j - 1 - L| ^ p) (0<=j<i)

f(i)表示将前i行诗放入整行的最小不协调度

s表示前缀和

可以使用1D1D动态规划,100分

  1. //不要去洛谷上面提交,洛谷的这题数据有问题,去codeVs
  2. #include<cstdio>
  3. #include<cstring>
  4. #define ll long double
  5. //node[i]代表i,里面的l代表决策的作用起点,r代表决策的作用终点,p是决策的值
  6. struct node{int l,r,p;}q[];
  7. #define MAX 1000000000000000000LL
  8. #define N 100100
  9. ll sum[N],f[N];
  10. int n,l,p,T;
  11. char ch[];
  12. //求|y|^p的函数
  13. ll pow(ll y){
  14. if(y<)y=-y;
  15. ll ans=;
  16. for (int i=;i<=p;i++) ans*=y;
  17. return ans;
  18. }
  19. //计算不协调度
  20. ll calc(int x,int y){
  21. return f[x]+pow(sum[y]-sum[x]+(y-x-)-l);
  22. }
  23. //二分查找找决策转折点
  24. //node表示老决策点,x表示新决策点的值
  25. //这个函数就是在老的决策点的范围中寻找新的决策点的值
  26. int find(node t,int x){
  27. int l=t.l,r=t.r;
  28. while(l<=r){//当头小于等于尾,也就是还有数可以查找的时候
  29. //mid=(头+尾)/2
  30. int mid=(l+r)>>;
  31. //小于的情况,也就是新的决策点更有,我们就要一直往前继续扩展新的决策点的起点,
  32. //直到老决策点比较好的时候
  33. if (calc(x,mid)<=calc(t.p,mid)) r=mid-;
  34. //大于的情况,也就老决策点比较好的时候,我们往后搜索新决策点的作用域的起点
  35. else l=mid+;
  36. }
  37. //返回头
  38. return l;
  39. }
  40.  
  41. void dp(){
  42. //用数组模拟栈,头置为1,尾置为0
  43. int head=,tail=;
  44. //将第一个决策入栈,决策1的起点为0,终点为n,决策的初始值置为0,因为初始决策就是0
  45. q[++tail]=(node){,n,};
  46. //求取f[i]
  47. for (int i=;i<=n;i++){
  48. //如果栈头结点上的决策作用终点小于i,说明这个决策已经无法对i进行作用,所以我们要换新的决策
  49. //head<=tail栈的头小于等于尾,说明栈里面还有新的决策,那就换上新的决策
  50. //因为head++,所以此时头节点是指向新的决策
  51. if(q[head].r<i&&head<=tail) head++;
  52. //用新的可以作用i位置的决策来计算f[i]的值,这样计算出来的f[i]的值就是最优值
  53. f[i]=calc(q[head].p,i);
  54. //calc(i,n)表示通过值为i的决策去计算f[n]的值
  55. //calc(q[tail].p,n)表示通过旧决策q[tail].p去计算f[n]的值
  56. //calc(i,n)<=calc(q[tail].p,n)表示值为i的决策优于老决策,我们才进行下一步
  57. //不然,如果老决策更好,我们根部用不着换决策
  58.  
  59. //每一个被计算出来的f[i],都会使i成为新的决策,因为我有了f[i]的值,
  60. //所以我可以用f[i]的值帮助计算别的f[k](k>i),所以f[i]就是新的决策
  61.  
  62. /*
  63. 比如说我们的样例1中,当i==3时,我们通过 q[head].p=2这个决策把f[3]算出来了
  64. 比如说这里的n是4,如果calc(3,4)<=calc(2,4),那说明值为3的这个新决策更好,
  65. 我们就要在决策2的作用区间里面找出决策3的作用区间
  66. */
  67.  
  68. //如果新决策更好,找出新决策的作用范围
  69. //确定新决策点的终点
  70. if (calc(i,n)<=calc(q[tail].p,n)){
  71. //如果栈的头小于等于尾,head<=tail,说明栈里有元素
  72. //calc(q[tail].p,q[tail].l)表示用旧决策点决策值来决策旧决策点的起点
  73. //calc(i,q[tail].l)用新决策点来决策旧决策点的起点
  74. //如果后者小于前者,说明新决更好,那就要在更广阔的范围里面去寻找新决策点的决策范围
  75. //换句话说,就是当新决策点的作用范围覆盖了老决策点,我们要到比旧决策点更老点决策点里面寻找新决策点的作用方位
  76. while(head<=tail&&calc(q[tail].p,q[tail].l)>=calc(i,q[tail].l)) tail--;
  77. //head>tail说明栈已经为空了,就是说现在新决策点最好,所以把新决策点入栈
  78. if(head>tail)q[++tail]=(node){i,n,i};
  79. else{
  80. //否则,我们就要去寻找新决策点的作用范围
  81. //x返回新决策点范围的起点
  82. int x=find(q[tail],i);
  83. //旧决策点的尾部置为x-1
  84. q[tail].r=x-;
  85. //将新决策点入栈
  86. q[++tail]=(node){x,n,i};
  87. }
  88. }
  89. }
  90. }
  91.  
  92. int main(){
  93. scanf("%d",&T);
  94. while(T--){
  95. scanf("%d%d%d",&n,&l,&p);
  96. for (int i=;i<=n;i++) scanf("%s",ch),sum[i]=sum[i-]+strlen(ch);
  97. dp();
  98. if(f[n]>MAX)
  99. puts("Too hard to arrange");
  100. else
  101. printf("%lld\n",(long long)f[n]);
  102. puts("--------------------");
  103. }
  104. return ;
  105. }

代码对应的分析

NOI 2009A 诗人小G的更多相关文章

  1. [BZOJ 1563] [NOI 2009] 诗人小G(决策单调性)

    [BZOJ 1563] [NOI 2009] 诗人小G(决策单调性) 题面 一首诗包含了若干个句子,对于一些连续的短句,可以将它们用空格隔开并放在一行中,注意一行中可以放的句子数目是没有限制的.小 G ...

  2. NOI 2009 诗人小G

    题目描述 Description 小G是一个出色的诗人,经常作诗自娱自乐.但是,他一直被一件事情所困扰,那就是诗的排版问题. 一首诗包含了若干个句子,对于一些连续的短句,可以将它们用空格隔开并放在一行 ...

  3. 解题:NOI 2009 诗人小G

    题面 今天考试考了,于是开始糊学决策单调性DP 这是一个完全不会优化DP的人 决策单调性DP的一种优化方法是用单调队列优化 存下{左端点l,右端点r,最优决策点p}的三元组,按照单调队列的通常操作来说 ...

  4. C++之路进阶——codevs2933(诗人小G)

    2933 诗人小G 2009年NOI全国竞赛  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 大师 Master     题目描述 Description 小G是一个出色的诗人 ...

  5. 【Luogu1912】【NOI2009】诗人小G(动态规划)

    [Luogu1912][NOI2009]诗人小G(动态规划) 题面 洛谷 题解 原来\(NOI\)这么多神仙题... 考虑一个极其明显的\(dp\) 设\(f[i]\)表示前\(i\)个句子产生的最小 ...

  6. LG1912 [NOI2009]诗人小G

    题意 题目描述 小G是一个出色的诗人,经常作诗自娱自乐.但是,他一直被一件事情所困扰,那就是诗的排版问题. 一首诗包含了若干个句子,对于一些连续的短句,可以将它们用空格隔开并放在一行中,注意一行中可以 ...

  7. bzoj1563: [NOI2009]诗人小G 决策单调性(1D1D)

    目录 题目链接 题解 代码 题目链接 bzoj1563: [NOI2009]诗人小G 题解 \(n^2\) 的dp长这样 \(f_i = min(f_j + (sum_i - sum_j - 1 - ...

  8. 1563: [NOI2009]诗人小G

    1563: [NOI2009]诗人小G https://lydsy.com/JudgeOnline/problem.php?id=1563 分析: 直接转移f[i]=f[j]+cost(i,j),co ...

  9. BZOJ1563/洛谷P1912 诗人小G 【四边形不等式优化dp】

    题目链接 洛谷P1912[原题,需输出方案] BZOJ1563[无SPJ,只需输出结果] 题解 四边形不等式 什么是四边形不等式? 一个定义域在整数上的函数\(val(i,j)\),满足对\(\for ...

随机推荐

  1. Java&Xml教程(七)使用JDOM修改XML文件内容

    JDOM提供了非常灵活的方式操作XML文件,使用JDOM非常简单而且代码简洁可读性强.前面我们学习了如何使用JDOM解析XML文件,本节介绍如何使用JDOM修改XML文件内容. 在这个教程中,我们准备 ...

  2. [Android]异常4-javax.mail.AuthenticationFailedException

    javax.mail.AuthenticationFailedException 背景:JavaMail发送电子邮件 异常原因: 可能一>发件人帐号.密码有误 可能二>需要使用SSL安全认 ...

  3. 初识关系型数据库(SQL)与非关系型数据库(NOSQL)

    一.关系型数据库(SQL): Mysql,oracle 特点:数据和数据之间,表和字段之间,表和表之间是存在关系的 例如:部门表 001部分,   员工表 001 用户表,用户名.密码 分类表 和 商 ...

  4. C# 获取表中最大值

    ; if (db.LPicture.Any()) { // LPicture Newmode = db.LPicture.Where(n => ).FirstOrDefault(); start ...

  5. CodeCombat代码全记录(Python学习利器)--Kithgard地牢代码1

    Kithgard地牢注意:在调用函数时,要在函数的后面加上括号内容,否则在python中,将不会认为你在调用这个函数内容,而你的英雄将像木头一样站在原地不会执行上左下右的移动!!! hero.move ...

  6. 构建秘钥对验证的SSH体系

    构建秘钥对验证的SSH 体系 首先先要在ssh 客户端以root用户身份创建秘钥对 客户端将创建的公钥文件上传至ssh服务器 服务器将公钥信息导入用户root的公钥数据库文件 客户端以root用户身份 ...

  7. html 报告页面 v1.2 批量数据生成表格

    html 报告页面 v1.2 批量数据生成表格 上代码: <!DOCTYPE html> <html lang="en"> <head> < ...

  8. S-HR之OSF

    1):getWorkDayCount ->ArrayList data = (ArrayList) com.kingdee.shr.rpts.ctrlreport.osf.OSFExecutor ...

  9. 求n!(高精度问题)

    #include <iostream> #include <stdio.h> #define MAX 10000 using namespace std; void Mul(i ...

  10. 25.TF&IDF算法以及向量空间模型算法

    主要知识点: boolean model IF/IDF vector space model     一.boolean model     在es做各种搜索进行打分排序时,会先用boolean mo ...