洛谷 P1281 書的複製

先說一下二分,二分其實就是跳着枚舉.一點點縮小區間,到最後就聚成一個點.中間能夠不用枚舉那麼多數.只\(check\)一下中間值\(mid\)是否能夠,而後再轉換到左半區間或者右半區間,這個看題目要求了.而後就這樣跳着走.\(so\) \(fast\);ios

\(check\)函數其實就是檢驗一下\(mid\)是否符合題目要求.大概平時都是\(bool\)型的.git

下面看一個例子題.
洛谷P1281 書的複製
題目描述
如今要把\(m\)本有順序的書分給\(k\)給人複製(抄寫),每個人的抄寫速度都同樣,一本書不容許給兩個(或以上)的人抄寫,分給每個人的書,必須是連續的,好比不能把第1、第3、第四本書給同一我的抄寫。函數

如今請你設計一種方案,使得複製時間最短。複製時間爲抄寫頁數最多的人用去的時間。
輸入格式
第一行兩個整數\(m,k;(k≤m≤500)\)spa

第二行\(m\)個整數,第\(i\)個整數表示第\(i\)本書的頁數。
輸出格式
\(k\)行,每行兩個整數,第\(i\)行表示第\(i\)我的抄寫的書的起始編號和終止編號。\(k\)行的起始編號應該從小到大排列,若是有多解,則儘量讓前面的人少抄寫。
輸入輸出樣例
輸入設計

9 3
1 2 3 4 5 6 7 8 9

輸出code

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\)找更小的,blog

\(check\)函數ip

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;
}

這道題,對我的認爲二分的考察不大,二分卻是不難寫,感受難寫的是輸出的時候有點費腦.get

總代碼string

#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;
}

附帥照

相關文章
相關標籤/搜索