第九章 動態規劃-1278:【例9.22】複製書稿(book)

1278:【例9.22】複製書稿(book)

時間限制: 1000 ms 內存限制: 65536 KB
【題目描述】
現在要把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


思路:最短時間爲抄寫頁數最多的時間,所以要先求最多的抄寫頁數,從中選擇最小值

  1. 設狀態:f[i][j]//將前i本書分給j個人抄寫需要的最短時間;
  2. 初始狀態:f[i][1];//一個人抄寫前i本書需要的最短時間就是前i本書的頁數
    最終狀態:f[m][k];//將前m本書分給j個人抄寫需要的最短時間
  3. 狀態轉移方程:先分配最後一個人抄寫的頁數,求得最大值 。max(f[i-l][j-1],d[i]-d[i-l]);
    最後求最短時間 f[i][j]=min{max(f[i-l][j-1],d[i]-d[i-l])}
    在用動態規劃求得最優值後,然後用貪心的思想,將最後一本書按逆序將書分配給k個人抄寫,從第k個人開始,如果他還能寫,就給他,直到分配完畢。
    在這裏插入圖片描述
#include<iostream>
#include<cstdio>
#define INF 0X3F3F3F3F
#define N 501
using namespace std;
int i,j,x,y,m,n,k,t,l;
int a[N];//存儲每本書的頁數
int f[N][N];//f[i][j]表示前i本書分給j個人抄寫的最短複製時間
int d[N];//d[j]表示前j本書的總頁數
int print(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[m][k])
	{
		x = x + a[t-1];
		t--;
	}
	print(t-1,j-1);
	cout << t << " " << i << endl;
}
int main()
{
	cin >> m >> k;
	for(i = 0;i <= 500;i++)
	{
		for(j = 0;j <= 500;j++)
		{
			f[i][j] = INF;//對f[i][j]進行初始化 
		}
	}	
	for(i = 1;i <= m;i++)
	{
		cin >> a[i];
		d[i] = d[i-1] + a[i];
		f[i][1] = d[i];//把前i本書都分給1個人抄寫需要的最短時間 
	}

	for(j = 2;j <= k;j++)//j個人  
	{
		for(i = 1;i <= m;i++)//i本書 
		{
			for(l = 1;l <= i-1;l++)//最後一個人抄寫的頁數
			{
				if(max(f[i-l][j-1],d[i]-d[i-l]) < f[i][j])
					f[i][j] = max(f[i-l][j-1],d[i]-d[i-l]);
			} 
		}
	}
	print(m,k);
} 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章