书的复制
LuoguP1281 书的复制
还有人写纯C吗 😄
简单二分?
只需要二分书的复制时间,再判断是否合法即可
判断复制时间是否合法的Code
bool isok(int x)
{
memset(as, 0, sizeof(as));
int l = 0, s = 0;
//ans[][0]:开始的位置,ans[][1]:结束的位置
for (int i = 1; i <= m;)
{
s = a[i], l++, as[l][0] = i, as[l][1] = i++;
//初始化
while(i<=m)
{
s += a[i], as[l][1]++;
if (s > x)
{
//如果大于就退出,让下一个人抄
as[l][1]--;
break;
}
i++;
}
}
if (l > k)//若抄完整本的人书大于限定的人数
return 0;
else
{
for (int i = 1; i <= l; i++)//存答案
ans[i][0] = as[i][0], ans[i][1] = as[i][1];
return 1;
}
}
但是
如果有多解,则尽可能让前面的人少抄写。
这简单,从最后一个人开始考虑即可,把一切都倒过来
完整\(Code\)
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#define M 600
int m, k, a[M], as[M][2], ans[M][2];
bool isok(int x)
{
memset(as, 0, sizeof(as));
int l = k + 1, s;
for (int i = m; i >= 1;)
{
s = a[i], l--, as[l][0] = i, as[l][1] = i--;
if (l < 1)
return 0;
for (; i >= 1; i--)
{
s += a[i], as[l][1]--;
if (s > x)
{
as[l][1]++;
break;
}
}
}
if (l < 1)
return 0;
else
{
for (int i = 1; i <= k; i++)
ans[i][0] = as[i][0], ans[i][1] = as[i][1];
return 1;
}
}
int main()
{
int l = 1, r = 0;
scanf("%d %d", &m, &k);
for (int i = 1; i <= m; i++)
scanf("%d", a + i), r += a[i];
while (l <= r)
{
int mid = (l + r) / 2;
if (isok(mid))
r = mid - 1;
else
l = mid + 1;
}
for (int i = 1; i <= k; i++)
printf("%d %d\n", ans[i][1], ans[i][0]);
return 0;
}
对吗?
请先阅读 \(https://www.luogu.com.cn/discuss/342875\)
可以这样想,如果,l-1==i
了,说明,剩下没分配的人数==书的数量
让他们每个人抄一本即可
所以判断函数应改为
bool isok(int x)
{
memset(as, 0, sizeof(as));
int l = k + 1, s;
for (int i = m; i >= 1;)
{
s = a[i], l--, as[l][0] = i, as[l][1] = i--;
if (l < 1)
return 0;
for (; i >= 1; i--)
{
s += a[i], as[l][1]--;
if (s > x)
{
as[l][1]++;
break;
}
}
}
if (l < 1)
return 0;
else
{
for (int i = 1; i <= k; i++)
ans[i][0] = as[i][0], ans[i][1] = as[i][1];
return 1;
}
}
附:正确样例
input:
6 5
1 1 1 1 1 1
output:
1 1
2 2
3 3
4 4
5 6