书的复制2021-06-22

洛谷绿题
题目传送门
题目背景
大多数人的错误原因:尽可能让前面的人少抄写,如果前几个人可以不写则不写,对应的人输出 0 0 。
不过,已经修改数据,保证每个人都有活可干。

题目描述
现在要把 m 本有顺序的书分给 k 个人复制(抄写),每一个人的抄写速度都一样,一本书不允许给两个(或以上)的人抄写,分给每一个人的书,必须是连续的,比如不能把第一、第三、第四本书给同一个人抄写。

现在请你设计一种方案,使得复制时间最短。复制时间为抄写页数最多的人用去的时间。
输入格式

第一行两个整数 m,k。

第二行 m 个整数,第 i 个整数表示第 i 本书的页数。
输出格式

共 k 行,每行两个整数,第 i 行表示第 i 个人抄写的书的起始编号和终止编号。 k行的起始编号应该从小到大排列,如果有多解,则尽可能让前面的人少抄写。

#include<cstdio>
#include<cstring>
int n,m,ans;
int a[510];
bool ch(int x) {
	int su=0,an=0;//an表示能分几个人
	//printf("%d\n",x);
	for(int i=n; i>=1; i--) {
		if(i==1) an++; //最后一人(最前面的)需要特殊处理
		if(su+a[i]<=x) {
			su+=a[i];
		} else {
			an++;
			su=a[i];
		}
	}
	if(an<=m) return 1;
	return 0;
}
void pr(int l,int r) { //打印当前左右边界内的部分
	int ss=0;
	for(int i=r; i>=l; i--) {
		if(ss+a[i]>ans) {
			pr(l,i);
			printf("%d %d\n",i+1,r);//逆序输出,回溯时才打印
			return ;
		}
		ss+=a[i];
	}
	printf("%d %d\n",1,r);//关于第一个人的特殊处理(边界)
	//第一组是不会超tim的
}
int main() {
	scanf("%d %d",&n,&m);
	if(n==0) return 0;// 判 0 的坑点,我wa了3次
	int l=0,r,mid;
	for(int i=1; i<=n; i++) {
		scanf("%d",&a[i]);
		r+=a[i];
	}
	// 二分模板
	while(l<=r) {
		mid=(l+r)/2;
		if(ch(mid)) {
			ans=mid; //ans存的就是每个人能分到的页数最大值,用这个来判输出
			r=mid-1;
		} else l=mid+1;
	}
	//printf("%d\n",ans);
	pr(1,n);// 打印函数(我用递归来实现的,直接倒推打循环也是可以的)
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值