- 1、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。。
- 2、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载。
- 3、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
查看更多
b 诗人小g
窗体顶端
窗体底端
您查询的关键词是:诗人小g?报告? 。如果打开速度慢,可以尝试快速版;如果想保存快照,可以添加到搜藏。
(百度和网页/blog/noi-2009-poet/的作者无关,不对其内容负责。百度快照谨为网络故障时之索引,不代表被搜索网站的即时页面。)
? Beyond the Void
? NOI 2009 变换序列
NOI 2009 二叉查找树 ?
一 12
NOI 2009 诗人小G
NOI Add comments1,500 views
问题简述
有N个诗句需要被排版为若干行,顺序不能改变。一行内可以有若干个诗句,相邻诗句之间有一个空格。定义行标准长度L,每行的不协调度为|实际长度-L|P,整首诗的不协调度就是每行不协调度之和。任务是安排一种排版方案,使得整首诗的不协调度最小。
问题建模
这是一个最优化问题,抽象成动态规划模型。设第i个诗句的长度为Len[i],前i个诗句的总长度为SumL[i],。F[i]为对前i个诗句排版的最小不协调度。
解法1 朴素的动态规划
算法描述
显然每个F[i]可以被分解为F[j]和第j+1…i个句子组成一行的状态,所以状态转移方程为
简化后,可以书写成
在具体实现时,应记录每个状态的决策,以便于输出合法方案。考虑到“最小的不协调度超过1018输出”Too hard to arrange””,为防止64位整型运算溢出,可以先用浮点数类型计算,然后再用整型算出具体值。
复杂度分析
状态数为O(N),每次转移需要以O(N)的时间枚举j,所以时间复杂度为O(N2)。在实际测试中通过了测试点1,2,3,得到30分。
参考程序
?View Code CPP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
/*
* Problem: NOI2009 poet
* Author: Guo Jiabao
* Time: 2009.9.22 13:30
* State: Solved
* Memo: 朴素动态规划
*/
#include iostream
#include cstdio
#include cstdlib
#include cmath
#include cstring
using namespace std;
?
typedef long long big;
?
const int MAXN=100001,SMAXL=32;
const big INF=~0ULL1,LIMIT=1000000000000000000LL;
?
big F[MAXN],sumL[MAXN];
int N,L,P;
int Len[MAXN],deci[MAXN],sel[MAXN];
char sent[MAXN][SMAXL];
?
void init()
{
scanf(%d%d%d\n,N,L,P);
for (int i=1;i=N;++i)
{
gets(sent[i]);
Len[i] = strlen(sent[i]);
sumL[i] = sumL[i-1] + Len[i];
}
}
?
big power(big a)
{
big t=1;
double dt=1;
if (a 0)
a = -a;
for (int i=1;i=P;i++)
{
dt *= a;
if (dt LIMIT)
return INF;
t *= a;
}
return t;
}
?
void solve()
{
int i,j,k;
big minv,t;
for (i=1;i=N;++i)
{
minv = INF;
for (j=0;j=i-1;++j)
{
t = power(sumL[i] - sumL[j] + i-j-1 - L);
if ( double(t) + double(F[j]) = LIMIT t + F[j] minv)
{
minv = t + F[j];
文档评论(0)