Problem Description
現在要把m本有順序的書分給k個人複製(抄寫),每一個人的抄寫速度都一樣,一本書不允許給兩個(或以上)的人抄寫,分給每一個人的書,必須是連續的,比如不能把第一、第三和第四本書給同一個人抄寫。
現在請你設計一種方案,使得複製時間最短。複製時間爲抄寫頁數最多的人用去的時間。
Input
輸入有多組數據,每組數據第1行兩個整數m,k(k<=m<=500);
第2行m個整數,第i個整數表示第i本書的頁數。
Output
對於每組數據輸出k行,每行兩個整數,第i行表示第i個人抄寫的書的起始編號和終止編號。k行的起始編號應該從小到大排列,如果有多解,則儘可能讓前面的人少抄寫。
Sample Input
9 3
1 2 3 4 5 6 7 8 9
Sample Output
1 5
6 7
8 9
//題解:由題意可知,求一個最優的平均值,使K段方差最小,最優解在1與輸入M本書的頁數之和之間,即用二分查找最優解。
//標程:(二分)
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int a[505], b[505], c[505];
int main()
{
// freopen("a.txt","r",stdin);
int n, k, i, j;
while(scanf("%d%d",&n,&k)!=EOF)
{
if(n == 0 && k == 0)
{
cout << endl;
continue;
}
int sum = 0;
for(i = 1; i <= n; ++ i)
{
cin >> a[i];
sum += a[i];
}
memset(b,0,sizeof(b));
memset(c,0,sizeof(c));
int l = 1, r = sum, mid;
while(l <= r)
{
mid = (l + r) / 2;
j = n;
for(i = 1; i <= k; ++ i)
{
int tmp = 0;
for(; j >= 1; j --)
if(tmp + a[j] <= mid)
tmp += a[j];
else break;
b[i] = j;
if(j == 0) break;
}
if(j == 0 && i <= k)
{
r = mid - 1;
for(i = 1; i <= k; ++ i)
c[i] = b[i];
}
else l = mid + 1;
}
c[0] = n;
for(i = k; i > 0; -- i)
cout << c[i] + 1 << ' ' << c[i-1] << endl;
}
return 0;
}
//關鍵字:DP
#include<cstdio>
#include<cstring>
int a[501],d[501];
int f[501][501];
int k,m;
int max(int a,int b) {return a>b?a:b;}
int min(int a,int b) {return a<b?a:b;}
void dg(int i,int j)
{
if (j==0) return;
if (j==1)
{
printf("1 %d\n",i);
return;
}
int t=i,x=a[i];
while (x+a[t-1]<=f[k][m])
{
x+=a[--t];
}
dg(t-1,j-1);
printf("%d %d\n",t,i);
}
int main()
{
// freopen("a.txt","r",stdin);
while(scanf("%d%d",&m,&k)!=EOF)
{
if(m==0&&k==0) {printf("\n"); continue;}
memset(f,0x3f,sizeof(f));
int i,j,l;
for (j=1;j<=m;j++)
{
scanf("%d",&a[j]);
d[j]=d[j-1]+a[j];
f[1][j]=d[j];
}
for (i=2;i<=k;i++) //第i個人
for (j=1;j<=m;j++) //到第j本書結束
for (l=1;l<j;l++)//從第l+1本書開始
f[i][j]=min(f[i][j],max(f[i-1][l],d[j]-d[l]));
dg(m,k);
}
return 0;
}
複製書稿
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.