1. 程式人生 > 其它 >資訊學奧賽一本通1278:複製書稿(evd)

資訊學奧賽一本通1278:複製書稿(evd)

技術標籤:經驗動態規劃

【題目描述】
現在要把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
【心得】線性DP的經典模型。課本上說的已經夠清楚了,不再贅述。
【AC程式碼】

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int N=505;
const int INF=0x7fffffff;
int m,k,a[N],d[N],f[N][N];
int pri(int i,int j)
{
	int t,x;
	if(j==0) return 0;
	if(j==1)
	{
		cout<<1
<<" "<<i<<endl; return 0; } t=i; x=a[i]; while(x+a[t-1]<=f[k][m]) { x=x+a[t-1]; t--; } pri(t-1,j-1); cout<<t<<" "<<i<<endl; } int main() { cin>>m>>k; for(int i=1;i<=m;i++) { cin>>a[i]; d[i]=d[
i-1]+a[i]; f[1][i]=d[i]; } for(int i=2;i<=k;i++) for(int j=1;j<=m;j++) f[i][j]=INF; for(int i=2;i<=k;i++) for(int j=1;j<=m;j++) for(int l=1;l<j;l++) f[i][j]=min(f[i][j],max(f[i-1][l],d[j]-d[l])); pri(m,k); }