{....................}hdoj1059
来源:互联网 发布:淘宝店铺访客突然暴跌 编辑:程序博客网 时间:2024/05/22 07:09
dp还接受得过去 字符串操作就。。。。恶心了
转poj的题解
/* * poj 1093 Formatting Text 数学模型: f[i]是以第i个单词为某行首,i到最后一个单词组成段落所能取得最小badness。 枚举与i同行的单词个数k,则有如下递归式成立: f(i) = min{f(i+k) + best_bad(i, i+k-1) | k->1 to m} 其中best_bad(i, i+k-1)表示从第i个单词(包含)起k个单词组成的行,所能取得的最小badness。 关于best_bad的求法,可以采用如下公式求解: best_bad(i, i+k-1) = (space_num/(k-1))^2 * (k-1) + (2*(space_num/(k-1)) + 1)*(space_num%(k-1)) 其中: space_num = [n - sum{len(j) | j->i to i+k-1} - (k-1)]; 关于本求法的证明有如下引理: 假设x+y=z,且有x'=x-t, y'=y+t则x^2+y^2 < x'^2+y'^2。-- 和一定的情况下,因子越是接近平均数,则其平方和越小。 证明: x'^2 + y'^2 = (x-t)^2 + (y+t)^2 = x^2 + y^2 + 2t^2 + 2(y-x)t > x^2 + y^2 */#include <iostream>#include <cstdio>#include <cstdlib>#include <cctype>#include <cstring>namespace { using namespace std; const int INFINITY = 0x7fffffff; // 正无穷 const int N_MAX = 10000; // 单词个数最大值 const int W_MAX = 80; // 行宽最大值 int length[N_MAX+1]; // 每个单词的长度 char words[N_MAX+1][W_MAX]; // 单词存储 int L; // 指定行宽 int n = 0; // 单词个数 int f[N_MAX+1]; int count[N_MAX+1]; int space[N_MAX+1]; void print(int no) { if (count[no]==1) // 只有一个单词的情况,直接输出 { printf("%s\n", words[no]); } else { // 计算各单词间的空格数 int spacenum, num; char space_format[16]; // 空格输出格式字符串 spacenum = space[no]/(count[no]-1)+1; num = (count[no]-1) - space[no]%(count[no]-1); sprintf(space_format, "%%s%%%ds", spacenum); int i=0; for (; i<num; i++) { printf(space_format, words[no+i], " "); } sprintf(space_format, "%%s%%%ds", spacenum+1); for (; i<(count[no]-1); i++) { printf(space_format, words[no+i], " "); } printf("%s\n", words[no+count[no]-1]); // 输出最后一个单词 } if (no+count[no] != n) // 输出后面的段落 { print(no+count[no]); } return; } #define square(x) \ ((x)*(x)) void format_text() { f[n] = 0; for (int i=n-1; i>=0; i--) // 从后向前求解,因为模型中前面的依赖后面的 { // 该行只有word[i]一个单词的情况 int curlen = length[i]; f[i] = f[i+1] + 500; // 只有一个单词时,badness为500 count[i] = 1; space[i] = 0; for (int k=2; k<=(n-i) && (curlen+length[i+k-1]+1)<=L; k++) // 枚举所有可能与word[i]在同一行的单词 { curlen += (length[i+k-1]+1); // 当前行单词总长度--包括各单词间必须的1个空格 int space_num = L - curlen; // 剩余用来分配的空格 // 剩余空格的最优分配方式 int bestbad = square(space_num/(k-1))*(k-1) + (2*(space_num/(k-1)) + 1)*(space_num%(k-1)); // 最优子问题的解组成原问题的最优解 if (f[i+k]+bestbad <= f[i]) // 塞尽可能多的单词,这里一定要是<=,否则会出现PE { f[i] = f[i+k]+bestbad; // 更新最优解 count[i] = k; space[i] = space_num; } } } print(0); }}int main(){ char line[N_MAX]; while (NULL!=gets(line) && EOF!=sscanf(line, "%d", &L)) { if (L == 0) break; n = 0; while (gets(line)) // 读入一行 { if (line[0]<33 || 126<line[0]) // 判断空行,这里采用并未line[0]=='\0'判断空行,因为windows下的回车是两个字符 break; int pos=0; int t=0; while (EOF != sscanf(&line[pos], "%s%n", words[n], &t)) // 格式符\n表示本次读过的字节数 { length[n] = strlen(words[n]); // 记录各单词的长度 ++n; pos += t; // 当前处理都得字符位置 t = 0; } } format_text(); // 格式化文本,并输出 printf("\n"); // 打印空行 } return 0;}另外,值得注意的两组数据:25x x x x x xxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxx x x x x x5La la la结果:x x x x x xxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxx x x x x xLa lala
- hdoj1059
- hdoj1059
- {....................}hdoj1059
- HDOJ1059
- HDOJ1059 Dividing
- HDOJ1059-Dividing(DP)
- hdoj1059 Dividing 多重背包
- hdoj1059 Dividing (水题)
- hdoj1059 Dividing(多重背包+二进制化简)
- 南阳理工OJ547---------------HDOJ1059---------多重背包~~~~有模板!!
- 让 C#智能注释时允许换行
- 黑马程序员 java入门:循环语句
- Hadoop Hive与Hbase整合
- Tomcat内存设置详解
- UML建模之用例图(UseCase Diagram)
- {....................}hdoj1059
- 让rm命令提示确认后再删除
- JS控制一个DIV层在指定时间内消失
- webkit Dump Render Tree 工作流程
- 一个简单的Duilib程序
- 如何高效地实现查询在一个表而不在另一个表中的记录
- c# 读取机器CPU信息,硬盘信息,网卡信息
- 钱宝网可靠吗? 不信可以先试用后在说
- web基础:Javascript