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分割的两块完美的连接起来
基本思想:空间换时间
比较容易想到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;
}