NOI 2009A 诗人小G
NOI 2009A 诗人小G
诗人小G
【问题描述】
小G是一个出色的诗人,经常作诗自娱自乐。但是,他一直被一件事情所困扰,那就是诗的排版问题。
一首诗包含了若干个句子,对于一些连续的短句,可以将它们用空格隔开并放在一行中, 注意一行中可以放的句子数目是没有限制的。小G给每首诗定义了一个行标准长度(行的长度为一行中符号的总个数),他希望排版后每行的长度都和行标准长度相差不远。显然排版时,不应改变原有的句子顺序,并且小G不允许把一个句子分在两行或者更多的行内。在满足上面两个条件的情况下,小G对于排版中的每行定义了一个不协调度, 为这行的实际长度与行标准长度差值绝对值的P次方,而一个排版的不协调度为所有行不协调度的总和。
小G最近又作了几首诗,现在请你对这首诗进行排版,使得排版后的诗尽量协调(即不协调度尽量小),并把排版的结果告诉他。
【输入文件】
输入文件poet.in包含多组数据。
第一行包含一个整数T,表示诗的数量,接下来是T首诗,这里一首诗即为一组数据。每组数据的第一行包含三个由空格分隔的正整数N、L、P,其中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分
//不要去洛谷上面提交,洛谷的这题数据有问题,去codeVs
#include<cstdio>
#include<cstring>
#define ll long double
//node[i]代表i,里面的l代表决策的作用起点,r代表决策的作用终点,p是决策的值
struct node{int l,r,p;}q[];
#define MAX 1000000000000000000LL
#define N 100100
ll sum[N],f[N];
int n,l,p,T;
char ch[];
//求|y|^p的函数
ll pow(ll y){
if(y<)y=-y;
ll ans=;
for (int i=;i<=p;i++) ans*=y;
return ans;
}
//计算不协调度
ll calc(int x,int y){
return f[x]+pow(sum[y]-sum[x]+(y-x-)-l);
}
//二分查找找决策转折点
//node表示老决策点,x表示新决策点的值
//这个函数就是在老的决策点的范围中寻找新的决策点的值
int find(node t,int x){
int l=t.l,r=t.r;
while(l<=r){//当头小于等于尾,也就是还有数可以查找的时候
//mid=(头+尾)/2
int mid=(l+r)>>;
//小于的情况,也就是新的决策点更有,我们就要一直往前继续扩展新的决策点的起点,
//直到老决策点比较好的时候
if (calc(x,mid)<=calc(t.p,mid)) r=mid-;
//大于的情况,也就老决策点比较好的时候,我们往后搜索新决策点的作用域的起点
else l=mid+;
}
//返回头
return l;
} void dp(){
//用数组模拟栈,头置为1,尾置为0
int head=,tail=;
//将第一个决策入栈,决策1的起点为0,终点为n,决策的初始值置为0,因为初始决策就是0
q[++tail]=(node){,n,};
//求取f[i]
for (int i=;i<=n;i++){
//如果栈头结点上的决策作用终点小于i,说明这个决策已经无法对i进行作用,所以我们要换新的决策
//head<=tail栈的头小于等于尾,说明栈里面还有新的决策,那就换上新的决策
//因为head++,所以此时头节点是指向新的决策
if(q[head].r<i&&head<=tail) head++;
//用新的可以作用i位置的决策来计算f[i]的值,这样计算出来的f[i]的值就是最优值
f[i]=calc(q[head].p,i);
//calc(i,n)表示通过值为i的决策去计算f[n]的值
//calc(q[tail].p,n)表示通过旧决策q[tail].p去计算f[n]的值
//calc(i,n)<=calc(q[tail].p,n)表示值为i的决策优于老决策,我们才进行下一步
//不然,如果老决策更好,我们根部用不着换决策 //每一个被计算出来的f[i],都会使i成为新的决策,因为我有了f[i]的值,
//所以我可以用f[i]的值帮助计算别的f[k](k>i),所以f[i]就是新的决策 /*
比如说我们的样例1中,当i==3时,我们通过 q[head].p=2这个决策把f[3]算出来了
比如说这里的n是4,如果calc(3,4)<=calc(2,4),那说明值为3的这个新决策更好,
我们就要在决策2的作用区间里面找出决策3的作用区间
*/ //如果新决策更好,找出新决策的作用范围
//确定新决策点的终点
if (calc(i,n)<=calc(q[tail].p,n)){
//如果栈的头小于等于尾,head<=tail,说明栈里有元素
//calc(q[tail].p,q[tail].l)表示用旧决策点决策值来决策旧决策点的起点
//calc(i,q[tail].l)用新决策点来决策旧决策点的起点
//如果后者小于前者,说明新决更好,那就要在更广阔的范围里面去寻找新决策点的决策范围
//换句话说,就是当新决策点的作用范围覆盖了老决策点,我们要到比旧决策点更老点决策点里面寻找新决策点的作用方位
while(head<=tail&&calc(q[tail].p,q[tail].l)>=calc(i,q[tail].l)) tail--;
//head>tail说明栈已经为空了,就是说现在新决策点最好,所以把新决策点入栈
if(head>tail)q[++tail]=(node){i,n,i};
else{
//否则,我们就要去寻找新决策点的作用范围
//x返回新决策点范围的起点
int x=find(q[tail],i);
//旧决策点的尾部置为x-1
q[tail].r=x-;
//将新决策点入栈
q[++tail]=(node){x,n,i};
}
}
}
} int main(){
scanf("%d",&T);
while(T--){
scanf("%d%d%d",&n,&l,&p);
for (int i=;i<=n;i++) scanf("%s",ch),sum[i]=sum[i-]+strlen(ch);
dp();
if(f[n]>MAX)
puts("Too hard to arrange");
else
printf("%lld\n",(long long)f[n]);
puts("--------------------");
}
return ;
}
代码对应的分析
NOI 2009A 诗人小G的更多相关文章
- [BZOJ 1563] [NOI 2009] 诗人小G(决策单调性)
[BZOJ 1563] [NOI 2009] 诗人小G(决策单调性) 题面 一首诗包含了若干个句子,对于一些连续的短句,可以将它们用空格隔开并放在一行中,注意一行中可以放的句子数目是没有限制的.小 G ...
- NOI 2009 诗人小G
题目描述 Description 小G是一个出色的诗人,经常作诗自娱自乐.但是,他一直被一件事情所困扰,那就是诗的排版问题. 一首诗包含了若干个句子,对于一些连续的短句,可以将它们用空格隔开并放在一行 ...
- 解题:NOI 2009 诗人小G
题面 今天考试考了,于是开始糊学决策单调性DP 这是一个完全不会优化DP的人 决策单调性DP的一种优化方法是用单调队列优化 存下{左端点l,右端点r,最优决策点p}的三元组,按照单调队列的通常操作来说 ...
- C++之路进阶——codevs2933(诗人小G)
2933 诗人小G 2009年NOI全国竞赛 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 大师 Master 题目描述 Description 小G是一个出色的诗人 ...
- 【Luogu1912】【NOI2009】诗人小G(动态规划)
[Luogu1912][NOI2009]诗人小G(动态规划) 题面 洛谷 题解 原来\(NOI\)这么多神仙题... 考虑一个极其明显的\(dp\) 设\(f[i]\)表示前\(i\)个句子产生的最小 ...
- LG1912 [NOI2009]诗人小G
题意 题目描述 小G是一个出色的诗人,经常作诗自娱自乐.但是,他一直被一件事情所困扰,那就是诗的排版问题. 一首诗包含了若干个句子,对于一些连续的短句,可以将它们用空格隔开并放在一行中,注意一行中可以 ...
- bzoj1563: [NOI2009]诗人小G 决策单调性(1D1D)
目录 题目链接 题解 代码 题目链接 bzoj1563: [NOI2009]诗人小G 题解 \(n^2\) 的dp长这样 \(f_i = min(f_j + (sum_i - sum_j - 1 - ...
- 1563: [NOI2009]诗人小G
1563: [NOI2009]诗人小G https://lydsy.com/JudgeOnline/problem.php?id=1563 分析: 直接转移f[i]=f[j]+cost(i,j),co ...
- BZOJ1563/洛谷P1912 诗人小G 【四边形不等式优化dp】
题目链接 洛谷P1912[原题,需输出方案] BZOJ1563[无SPJ,只需输出结果] 题解 四边形不等式 什么是四边形不等式? 一个定义域在整数上的函数\(val(i,j)\),满足对\(\for ...
随机推荐
- mongoDB 删除集合后,空间不释放的解决方法
mongoDB 删除集合后,空间不释放,添加新集合,没有重新利用之前删除集合所空出来的空间,也就是数据库大小只增不减. 方法有: 1.导出导入 dump & restore 2.修复数据库 r ...
- [Windows Server 2008] ASP.net安装方法
★ 欢迎来到[护卫神·V课堂],网站地址:http://v.huweishen.com★ 护卫神·V课堂 是护卫神旗下专业提供服务器教学视频的网站,每周更新视频.★ 本节我们将带领大家:安装ASP.n ...
- Tcl之Lab1
Task 1. Use help 1) What is the default switch for the redirect command? -file help -v redirect # or ...
- Java_Web三大框架之Hibernate+jsp+HQL分页查询
分页查询无处不在.使用Hibernate+jsp+HQL进行分页查询. 第一步:编写房屋实体类和House.hbm.xml映射. /* * 房屋实体类 */ public class House { ...
- Ubuntu 关闭guest用户
Ubuntu 关闭guest用户 ca0gu0@ub:~$ cat /etc/lightdm/lightdm.conf [SeatDefaults]autologin-user=falseallow- ...
- Centos6.4 安装bind dns 服务器
一.介绍 1)Centos6.4 64bit minimal 2) bind-9.8.2-0.30.rc1.el6_6.3.x86_64 二.安装 $ yum install -y bind bind ...
- Discuz! G变量的使用方法
1,G变量的使用方法: 例如:$_G['style'][boardlogo] 风格变量篇 $_G['style'] => Array (官方模板区 cr180整理 $_G['style'][st ...
- Android获取SD卡路径/内存的几种方法
Android获取SD卡路径 本篇将会带领大家学习如何获取android路径的几种常见用法,但在我开始bb之前需要大家清楚android中内存和外存之间的区别,下面进行简短介绍:android中的内存 ...
- @Override注解
@Override注解对于代码可读性的提升十分巨大 而且良好的可读性是一个优秀程序员必备的基础素养
- Django工程
一.Django工程创建 1.Django安装: pip3 install django 安装成功后,会在python的安装目录下“Scripts"中生成”django-admin.exe& ...