Description 题目描述
现在要把 M M M本有顺序的书分给 K K K个人复制(抄写),每一个人的抄写速度都一样,一本书不允许给两个(或以上)的人抄写,分给每一个人的书,必须是连续的,比如不能把第一、第三、第四本书给同一个人抄写。现在请你设计一种方案,使得复制时间最短。复制时间为抄写页数最多的人用去的时间。
Input 输入
第一行两个整数 M 、 K M、K M、K; ( 0 ≤ K ≤ M ≤ 500 ) (0≤K≤M≤500) (0≤K≤M≤500)
第二行 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][i−1],sum[k+1,i]))
输出贪心思路搞定
上代码
#include <cstdio>
#include <climits>
#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
引用学长一句话:
男人,要直面自己的弱点…