尼克的任務(0410)
尼克的一個工作日爲N分鐘,從第一分鐘開始到第N分鐘結束。當尼克到達單位後他就開始幹活。如果在同一時刻有多個任務需要完成,尼克可以任選其中的一個來做,而其餘的則由他的同事完成,反之如果只有一個任務,則該任務必需由尼克去完成,假如某些任務開始時刻尼克正在工作,則這些任務也由尼克的同事完成。如果某任務於第P分鐘開始,持續時間爲T分鐘,則該任務將在第P+T-1分鐘結束。
寫一個程序計算尼克應該如何選取任務,才能獲得最大的空暇時間。
接下來共有K行,每一行有兩個用空格隔開的整數P和T,表示該任務從第P分鐘開始,持續時間爲T分鐘,其中1≤P≤N,1≤P+T-1≤N。
1
2
3
4
5
6
7
|
15 6
1 2
1 6
4 11
8 5
8 1
11 5
|
1
|
4
|
#include<iostream>
#include<string.h>
#include<algorithm>
using namespace std;
int dp[20000];//dp[i]表示如果當前在i分鐘,我能獲得的最大空閒時間
int n,k;
struct sta{
int start;//開始時間
int len;//持續時間
};
bool cmp(sta a, sta b)
{
return a.start > b.start;
}
int main()
{
while (cin >> n >> k)
{
sta data[20000] = { 0 };//儲存所有的工作
memset(dp, 0, sizeof(dp));//默認每一分鐘剛開始空閒時間都是0 **
for (int i = 0; i < k; i++)cin >> data[i].start >> data[i].len;//讀取所有工作
sort(data, data + k,cmp);//工作表按開始時間由大到小排好序,好整理
//從最後一組開始往前
for (int i = n ,j= 0; i >= 1; i--)//i用於表示當前是多少分鐘,j用於標記當前工作時間表讀到哪一組了
{
if (i != data[j].start)dp[i] = dp[i + 1] + 1;//如果這一分鐘沒有工作的話,我能比下一分鐘多一分鐘的空閒
else {
//如果當前這一分鐘有工作
while (data[j].start == i)//我就把所有當前時間的工作看一遍
{
//第一次循環到這裏的時候,dp[i]還沒處理過,i分鐘的空閒時間還等於0 **
if (dp[i + data[j].len]>dp[i])//dp[i+data[j].len]表示如果我選擇當前這個工作,我的空閒時間和i+data[j].len分鐘後是一樣的,因爲在這期間我沒有增加空閒時間
{
//然後比較是我保存的dp[i]的空閒時間多,還是我接受這個工作能獲得的空閒時間更多
//第一次的時候,i時刻的空閒時間爲0,i+data[j].len時刻的空閒時間一定大於0,所以第一份工作是必須接受
//然後多次循環,比較後面的在i時刻開始的工作,尋找能獲得最大空閒時間的
dp[i] = dp[i + data[j].len];
}
j++;
}
}
}
cout << dp[1] << endl;
}
return 0;
}