您的位置:首页 > 运维架构

UVa 714 - Copying Books

2013-08-22 16:54 309 查看
  题目大意:有m本书,每本书有pi页,把这m本书分给k个人抄写,如何分配才能在最短的时间抄写完这m本书。

  最大值最小化问题:把一个包含n个正整数的序列划分成m个连续的子序列,设第i个序列的各数之和为S(i), 使得所有S(i)的最大值尽量小。序列最大值为max,所有数之和为sum,则所求答案必定在[max, sum]之间,通过二分法判断中值mid是否符合条件(把序列分为m份,每份均不超过mid)逐步缩小范围,直至求得解。

  其实,我觉得还是看代码来的直接,看书上说的东西半天也不理解说的什么意思,还是研究代码可以一点点地理解。

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define MAXN 500+10

long long p[MAXN];
int m, k;
bool cut[MAXN];

bool judge(long long n)
{
long long sum = 0;
int cnt = 0;
for (int i = 0; i < m; i++)
{
if (sum + p[i] > n)
{
sum = 0;
cnt++;
}
sum += p[i];
}
cnt++;
if (cnt > k)  return false;
return true;
}

int main()
{
#ifdef LOCAL
freopen("in", "r", stdin);
#endif
int T;
scanf("%d", &T);
while (T--)
{
scanf("%d%d", &m, &k);
long long sum = 0, lmax = 0;
for (int i = 0; i < m; i++)
{
scanf("%lld", &p[i]);
sum += p[i];
lmax = max(lmax, p[i]);
}
long long low = lmax, high = sum;
while (low < high)
{
long long mid = (low + high) / 2;
if (judge(mid))  high = mid;
else  low = mid + 1;
}
long long ans = low;
int remain = k - 1;
memset(cut, 0, sizeof(cut));
sum = 0;
for (int i = m-1; i >= 0; i--)
{
if (i+1 > remain && sum + p[i] <= ans)
{
sum += p[i];
}
else
{
cut[i] = true;
sum = p[i];
remain--;
}
}
for (int i = 0; i < m; i++)
{
printf("%lld%s", p[i], (i == m-1) ? "\n" : " ");
if (cut[i])  printf("/ ");
}
}
return 0;
}


View Code
  最后的输出把我纠结地快疯了,本来也不是很麻烦,可是因为参考别人代码一会就把自己弄迷糊了,果然有些东西还是按自己思路写更自然、快速。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: