第3章 动态规划,算法分析题3-3 漂亮打印

第3章 动态规划,算法分析题3-3 漂亮打印_第1张图片


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

你可能感兴趣的:(动态规划)