n代表单词的数目;
mlen代表一行可以打印的最大长度;
m[i]表示:以第i个单词作为打印的第一个单词时,打印的最小‘丑陋’值为m[i];
len()函数返回改行打印第i个数到第j个数时的所占长度;
ugly()函数根据改行打印的长度返回‘丑陋’值。
注:题目中要求的最漂亮的打印方案,所以‘丑陋’值越小,越漂亮。
动态规划法:
#include <iostream> #include <cstdio> using namespace std; #define MAXN 100 #define INF 0x7FFFFFFF int wl[MAXN]; //wl[i]表示:第i个单词的长度 int m[MAXN]; //m[i]表示:从第i个单词开始打印所得的最小'丑陋'值 int tail[MAXN]; //tail[i]表示:从第i个单词开始打印取得最小'丑陋'值时,第一行最后一个单词的标号 int UglyValue(int len, int maxLen) { return (maxLen-len)*(maxLen-len)*(maxLen-len); } int PrettyPrint(int n, int maxLen) { m[n] = 0; tail[n] = n; int i, j; //以第i个单词作为打印的第一个单词 for (i = n-1; i >= 1; i--) { m[i] = INF; int len = -1; for (j = i; j <= n; j++) { //第一行的长度 len += (wl[j] + 1); if (len > maxLen) { break; } //计算'丑陋'值 int value = 0; if (j != n) //j==n时,第一行就是最后一行,所以'丑陋'值为0 { value = UglyValue(len, maxLen) + m[j+1]; } //printf("i: %d j: %d value: %d\n", i, j, value); if (value < m[i]) { m[i] = value; tail[i] = j; } } } return m[1]; } int main(void) { int n, maxLen; while (scanf("%d%d", &n, &maxLen) != EOF) { int i; for (i = 1; i <= n; i++) { scanf("%d", &wl[i]); } printf("%d\n", PrettyPrint(n, maxLen)); for (i = tail[1]; i != n; i = tail[i+1]) { printf("%d ", i); } printf("%d\n", n); } return 0; }
#include <iostream> #include <cstdio> using namespace std; #define MAXN 100 #define INF 0x7FFFFFFF int n; int wl[MAXN]; int mem[MAXN]; int tail[MAXN]; int maxLen; int UglyValue(int len) { return (maxLen-len)*(maxLen-len)*(maxLen-len); } int PrettyPrint(int k, int lineID) { int minValue = INF; int len = -1; int i; for (i = k; i <= n; i++) { len += (wl[i] + 1); if (len > maxLen) { break; } int value = 0; if (i != n) { if (mem[i+1] == -1) { mem[i+1] = PrettyPrint(i+1, lineID+1); } value = (mem[i+1] + UglyValue(len)); } if (value < minValue) { minValue = value; tail[k] = i; } } //printf("k: %d minValue: %d\n", k, minValue); return minValue; } int main(void) { while (scanf("%d%d", &n, &maxLen) != EOF) { int i; for (i = 1; i <= n; i++) { scanf("%d", &wl[i]); } memset(mem, -1, sizeof(mem)); printf("%d\n", PrettyPrint(1, 1)); for (i = tail[1]; i != n; i = tail[i+1]) { printf("%d ", i); } printf("%d\n", n); } return 0; }
5 11
3 4 2 7 4
5 11
3 4 2 7 3
5 10
3 4 2 7 4
10 15
3 9 4 7 2 3 4 1 8 5