题目:https://www.luogu.org/problemnew/show/P1280
题意:
给定k个任务的开始时间和持续时间要求在n时间内完成。问如何安排工作使得休息时间最多。
思路:
用dp[i]表示i~n的时间内的最长休息时间。
每一个时间点只有两种可能:有工作or没有工作在此时开始
如果没有工作,那么只用上一个空闲时间+1就行了
如果有工作,那么也只有两种选择,做或者不做。也就是dp[i]和dp[i+mission[id].last]中选择较大者。
从后往前推是因为前面的时间点的选择不会受到后面任务的选择的影响。但是如果从前往后推,前面的任务选或不选会影响到后面。
1 #include<cstdio> 2 #include<cstdlib> 3 #include<map> 4 #include<set> 5 #include<cstring> 6 #include<algorithm> 7 #include<vector> 8 #include<cmath> 9 #include<stack> 10 #include<queue> 11 #include<iostream> 12 13 #define inf 0x7fffffff 14 using namespace std; 15 typedef long long LL; 16 typedef pair<string, string> pr; 17 18 int n, k; 19 const int maxn = 1e4 + 5; 20 struct node{ 21 int st; 22 int last; 23 }mission[maxn]; 24 int dp[maxn], vis[maxn]; 25 26 bool cmp(node a, node b) 27 { 28 return a.st > b.st; 29 } 30 31 int main() 32 { 33 scanf("%d%d", &n, &k); 34 for(int i = 1; i <= k; i++){ 35 scanf("%d%d", &mission[i].st, &mission[i].last); 36 vis[mission[i].st]++; 37 } 38 sort(mission + 1, mission + 1 + k, cmp); 39 int id = 1; 40 // for(int i = 1; i <= n; i++){ 41 // if(!vis[i])dp[i] = dp[i - 1] + 1; 42 // for(int j = 1; j <= vis[i]; j++){ 43 // dp[i] = max(dp[i], dp[i - mission[id].last]); 44 // id++; 45 // } 46 // } 47 // printf("%d ", dp[n]); 48 for(int i = n; i >= 1; i--){ 49 if(!vis[i])dp[i] = dp[i + 1] + 1; 50 for(int j = 1; j <= vis[i]; j++){ 51 dp[i] = max(dp[i], dp[i + mission[id].last]); 52 id++; 53 } 54 } 55 56 printf("%d ", dp[1]); 57 58 return 0; 59 }