[二分] [CodeVS3162] 抄书问题

Description 题目描述

现在要把 M M M本有顺序的书分给 K K K个人复制(抄写),每一个人的抄写速度都一样,一本书不允许给两个(或以上)的人抄写,分给每一个人的书,必须是连续的,比如不能把第一、第三、第四本书给同一个人抄写。现在请你设计一种方案,使得复制时间最短。复制时间为抄写页数最多的人用去的时间。

Input 输入

第一行两个整数 M 、 K M、K MK ( 0 ≤ K ≤ M ≤ 500 ) (0≤K≤M≤500) 0KM500
第二行 M M M个整数,第 i i i个整数表示第 i i i本书的页数。

Output 输出

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

Sample Input 样例输入

9 3
1 2 3 4 5 6 7 8 9

Sample Output 样例输出

1 5
6 7
8 9

Limits 限制

详见试题
Time Limit : 1 s 1s 1s & Memory Limit : 128 M B 128MB 128MB

第一次见到这题是考试的时候
不会啊!!!
什么都没输出,得了10分(rp就这么用光了…)
首先可以dp做
d p [ i ] [ j ] dp[i][j] dp[i][j]表示前 i i i页书被 j j j个人抄,抄写最多的页数
d p [ i ] [ j ] dp[i][j] dp[i][j]= m i n ( m a x ( d p [ k ] [ i − 1 ] , s u m [ k + 1 , i ] ) ) min(max(dp[k][i-1],sum[k+1,i])) min(max(dp[k][i1],sum[k+1,i]))
输出贪心思路搞定
上代码

#include  
#include  
#define MAXN 1100 
using namespace std; 
  
int dp[MAXN][MAXN]; 
int ans[MAXN][2]; 
int n,k,m,i,j; 
int p,q,cnt; 
int a[MAXN]; 
int sum[MAXN]; 
  
int mymax(int a,int b) 
{ 
    return a>b?a:b; 
} 
int main() 
{ 
    scanf("%d %d",&n,&k); 
    for(i=1;i<=n;i++) 
        for(j=1;j<=k;j++) 
            dp[i][j]=INT_MAX; 
    for(int i=1;i<=n;i++) 
    { 
        scanf("%d",&a[i]); 
        sum[i]=sum[i-1]+a[i]; 
        dp[i][1]=sum[i]; 
    } 
    for(m=2;m<=k;m++) 
        for(i=1;i<=n;i++) 
            for(j=1;j<i;j++) 
            { 
                if(dp[i][m]>mymax(dp[j][m-1],sum[i]-sum[j])) 
                    dp[i][m]=mymax(dp[j][m-1],sum[i]-sum[j]); 
            } 
    p=n,q=k; 
    for(i=n;i>=1;i--) 
    { 
        cnt+=a[i]; 
        if(cnt>dp[n][k]) 
        { 
            ans[q][0]=i+1; 
            ans[q][1]=p; 
            p=i; 
            q--; 
            cnt=a[i]; 
        } 
    } 
    ans[1][0]=1;ans[1][1]=p; 
    for(int i=1;i<=k;i++) 
    if (ans[i][0]&&ans[i][1]) 
        printf("%d %d\n",ans[i][0],ans[i][1]); 
    return 0; 
} 

但是有点卡时……
正解是二分答案,类似 NOIP 2015 跳石头的思路。
Code

引用学长一句话:
男人,要直面自己的弱点…

你可能感兴趣的:(贪心,二分)