图片排版

http://hihocoder.com/problemset/problem/1365?sid=863390
基本思想:空间换时间
比较容易想到O(n^2)的解决方案,遍历n种删除可能,每次遍历O(n)时间求总高度
前者优化比较困难,因而想办法优化每次遍历求高度的时间

做题时想到了记录分别从各个图片开始排版时的总高度,但未能利用好它去求删除第i个图片后的总高度
关键点:
1. 由前往后遍历,当删除第i个图片时,先前的图片排版是连续的,从而通过计数器等累加方法可以求得已完整行的总高度preSum,以及当前未完整行的w,h
2. calc()函数计算时扩展了w,h两个参数(更灵活了,当时没有想到),第i+1个图片调用它从而可以将图片i分割的两块完美的连接起来

3. 浮点数的计算精度问题,先除后乘WA, 先乘后除AC了


具体实现:

#include 
#include 
using namespace std;

#define SIZE 100005
int M, N, wi[SIZE], hi[SIZE], t[SIZE];

void attach(int i, int &w, int &h)
{
	if (w + wi[i] > M)
		h = max(h, (int)ceil(1.0 * (M - w) * hi[i] / wi[i]));
	else
		h = max(h, hi[i]);
	w = min(M, w + wi[i]);
}

int calc(int i, int w, int h)
{
	while (i < N && w < M)
		attach(i++, w, h);
	return h + t[i];
}

void init()
{
	cin >> M >> N;
	for (int i = 0; i < N; ++i)
		cin >> wi[i] >> hi[i];
	for (int i = N - 1; i >= 0; --i)
		t[i] = calc(i, 0, 0);
}

void solve()
{
	int ans, w, h, preSum, tmp;
	ans = 10000000, w = h = preSum = 0;
	for (int i = 0; i < N; ++i)
	{
		tmp = calc(i + 1, w, h);
		ans = min(ans, preSum + tmp);
		attach(i, w, h);
		if (w == M)
		{
			preSum += h;
			w = h = 0;
		}
	}
	cout << ans << endl;
}

int main()
{
	init();
	solve();
	return 0;
}

你可能感兴趣的:(hihocoder,算法)