zoukankan      html  css  js  c++  java
  • 洛谷 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
    ",max(b[ojk][1]-1,1));
    	for(int i=ojk;i>=1;i--)
    	printf("%d %d
    ",b[i][1],b[i][2]);
    	return 0;
    }
    

    附帅照

  • 相关阅读:
    UG二次开发-CAM-获取修改路径参数
    多线程01
    MFC的对话框使用Scintilla
    CATIA的后处理
    win32窗体中使用Scintilla窗体
    string的reserve和resize
    前端宝典
    MarkDown学习
    JAVA中构造方法总结
    IDEA中maven和tomcat的配置
  • 原文地址:https://www.cnblogs.com/Xchu/p/11706672.html
Copyright © 2011-2022 走看看