欢迎来到xXchu的博客
xXchu
xXchu
晓看天色暮看云,行也思君,坐也思君

洛谷 P1281 书的复制

先说一下二分,二分其实就是跳着枚举.一点点缩小区间,到最后就聚成一个点.中间可以不用枚举那么多数.只\(check\)一下中间值\(mid\)是否可以,然后再转换到左半区间或者右半区间,这个看题目要求了.然后就这样跳着走.\(so\) \(fast\);

\(check\)函数其实就是检验一下\(mid\)是否符合题目要求.大概平时都是\(bool\)型的.

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

现在请你设计一种方案,使得复制时间最短。复制时间为抄写页数最多的人用去的时间。
输入格式
第一行两个整数\(m,k;(k≤m≤500)\)

第二行\(m\)个整数,第\(i\)个整数表示第\(i\)本书的页数。
输出格式
\(k\)行,每行两个整数,第\(i\)行表示第\(i\)个人抄写的书的起始编号和终止编号。\(k\)行的起始编号应该从小到大排列,如果有多解,则尽可能让前面的人少抄写。
输入输出样例
输入

9 3
1 2 3 4 5 6 7 8 9

输出

1 5
6 7
8 9

思路
所有每个人的页数最大值在\(1到\sum_{i=1}^na_i\) 之间,所以0左右左端点,\(\sum_{i=1}^na_i\)作为右端点,就可以开始二分了,\(check\)函数,如果遇到了比\(mid\)页数大的书,那么每个人最多\(mid\)页也没法整完这一本因为一本书只能给一个人,然后就左端点\(=mid+1\)继续找更大的,否则就右端点\(=mid-1\)找更小的,

\(check\)函数

bool check(int x)
{		
	int tot=0,js=0;
	for(int i=m;i>=1;i--)
	{
		if(i==1)
		js++; 
		if(a[i]>x)
		return false;
		if(tot+a[i]<=x)//累加
		tot+=a[i];
		else//如果这个人不能再继续抄下一本了就换一个新人,
		tot=a[i],js++;
	}
	return js<=k;
}

这道题,对个人认为二分的考察不大,二分倒是不难写,感觉难写的是输出的时候有点费脑.

总代码

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<string>
#include<algorithm>
#include<iomanip>
#include<cstdlib>
#include<queue>
#include<map>
#include<set>
#include<stack>
#include<vector>
#define ll long long
using namespace std;
inline int read()
{
   int s=0,w=1;
   char ch=getchar();
   while(!isdigit(ch)){if(ch=='-')w=-1;ch=getchar();}
   while(isdigit(ch)) s=s*10+ch-'0',ch=getchar();
   return s*w;
}
int m,k,a[550],l,r,x,jb,okoj,jk,b[550][5],ojk,js;
bool check(int x)
{		
	int tot=0,js=0;
	for(int i=m;i>=1;i--)
	{
		if(i==1)
		js++; 
		if(a[i]>x)
		return false;
		if(tot+a[i]<=x)
		tot+=a[i];
		else
		tot=a[i],js++;
	}
	return js<=k;
}
int main()
{
	m=read(),k=read();
	if(m==0&&k==0)
	return 0;
	for(int i=1;i<=m;i++)
	a[i]=read(),js+=a[i];
	l=0,r=js;
	while(l<=r)
	{
		int mid=l+r>>1;
		if(check(mid))
		okoj=mid,r=mid-1;
		else
		l=mid+1;
	}
	x=m;
	for(int i=m;i>=1;i--)
	{
		jb+=a[i];
		if(jb>l)
		{
			b[++ojk][1]=i+1,b[ojk][2]=x;
			jb=a[i],x=i;
		}
	}
	if(js<=l)
	{
		return printf("1 %d",m),0;
	}
	printf("1 %d\n",max(b[ojk][1]-1,1));
	for(int i=ojk;i>=1;i--)
	printf("%d %d\n",b[i][1],b[i][2]);
	return 0;
}

附帅照

posted @ 2019-10-20 08:42  xXchu  阅读(257)  评论(2编辑  收藏  举报