uva 709 - Formatting Text(记忆化搜索)
题目连接:709 - Formatting Text
题目大意:给n,然后在给出一篇文章,有若干个单词,以空行结束,现在要将文章排序使得文章的badness 越小。
badness 的计算方法,如果一行只有一个单词的话,若单词的长度小于n,则badness 增加500,否则为0。
若一行有多个单词,每两个单词之间的badness = (c - 1) ^ 2 (c为两个单词的空格数),要求,每行控制长度在n,并且前一个单词顶头,后一个单词顶尾(一个单次的情况除外)
注意:输出文章方案的时候,若一行只有一个单词的时候,要直接回车,不能在输出空格。否则会PE,但是POJ上就可以过。
#include <stdio.h>#include <string.h>#include <math.h>const int L = 100;const int N = 1005;const int INF = 1 << 30;int n, row, len[N], dp[N][N], rec[N][N];char word[N][L], str[N];void handle(char s[]) {int l = strlen(s);for (int i = 0; s[i]; ) { sscanf(s + i, "%s", word[n]); len[n] = strlen(word[n]); i += len[n++];while (s[i] == ' ') i++; }}void init() {n = 0;sscanf(str, "%d", &row);row++;while (gets(str)) {if (!str[0]) break;handle(str);}}int solve(int x, int y) {if (dp[x][y] > -1) return dp[x][y];if (x == n) {if (y != 0) return INF;else return 0;}int& ans = dp[x][y];int& p = rec[x][y];int begin = y + len[x] + 1, end = row - len[x + 1], t;ans = INF;if (!y) {t = solve(x + 1, 0) + 500;if (t < ans) {ans = t;rec[x][y] = 0;}}if (begin == row) {t = solve(x + 1, 0);if (t < ans) {ans = t;rec[x][y] = 0;}}for (int i = begin; i <= end; i++) {t = solve(x + 1, i) + (i - begin) * (i - begin);if (t < ans) {ans = t;rec[x][y] = i;}}return ans;}void put() {int x = 0, y = 0;row--;while (x < n) {for (int i = 0; i < row;) {if (i == y) {printf("%s", word[x]);i += len[x];y = rec[x][y];x++;}else if (i > y) break;else {printf(" ");i++;}}printf("\n");}/* for (int i = 0, j = 0; i < n; i++) { printf("%s", word[i]); if (rec[i][j] > 0) { int x = sqrt(dp[i][j]-dp[i+1][rec[i][j]]); for (int k = 0; k <= x; k++) printf(" "); } else printf("\n"); j = rec[i][j]; } */}int main () {while (gets(str)) {init();if (row == 1) break;memset(dp, -1, sizeof(dp));solve(0, 0);put();printf("\n");}return 0;}