1280 尼克的任务

难度:普及+/提高

题目类型:动规

提交次数:1

涉及知识:线性动规

题目描述

尼克每天上班之前都连接上英特网,接收他的上司发来的邮件,这些邮件包含了尼克主管的部门当天要完成的全部任务,每个任务由一个开始时刻与一个持续时间构成。

尼克的一个工作日为N分钟,从第一分钟开始到第N分钟结束。当尼克到达单位后他就开始干活。如果在同一时刻有多个任务需要完戍,尼克可以任选其中的一个来做,而其余的则由他的同事完成,反之如果只有一个任务,则该任务必需由尼克去完成,假如某些任务开始时刻尼克正在工作,则这些任务也由尼克的同事完成。如果某任务于第P分钟开始,持续时间为T分钟,则该任务将在第P+T-1分钟结束。

写一个程序计算尼克应该如何选取任务,才能获得最大的空暇时间。

输入输出格式

输入格式:

输入数据第一行含两个用空格隔开的整数N和K(1≤N≤10000,1≤K≤10000),N表示尼克的工作时间,单位为分钟,K表示任务总数。

接下来共有K行,每一行有两个用空格隔开的整数P和T,表示该任务从第P分钟开始,持续时间为T分钟,其中1≤P≤N,1≤P+T-1≤N。

输出格式:

输出文件仅一行,包含一个整数,表示尼克可能获得的最大空暇时间。

代码:

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<vector>
 4 using namespace std;
 5 int n, k;
 6 struct task{
 7     int start;
 8     int last;
 9     int end;
10 };
11 bool com(task a, task b){
12     return a.start<b.start;
13 }
14 int d[10010];//表示以第i个任务结尾的工作序列的最小消耗时间
15 int b[10010];//表示第i分钟开始的任务个数
16 int s[10010];//表示第1到i分钟的任务个数
17 int main(){
18     cin>>n>>k;
19     int i, j;
20     vector<task>a(k+1);
21     for(i = 1; i <= k; i++){
22         int start, last, end;
23         cin>>start>>last;
24         end = start+last-1;
25         a[i].start = start;
26         a[i].end = end;
27         a[i].last = last;
28         b[start]++;
29     }
30     sort(a.begin()+1, a.end(), com);
31
32     for(i = 1; i <= n; i++)
33         s[i] = s[i-1]+b[i];
34
35     for(i = 1; i <=k; i++){
36         d[i] = 10010;
37         for(j = 0; j < i; j++){
38             if(a[j].end<a[i].start&&s[a[j].end]==s[a[i].start-1])
39                 d[i] = min(d[i], d[j]+a[i].last);
40         }
41     }
42     int ans = 10010;
43     for(i = 1; i <=k; i++){
44         if(s[a[i].end]==s[n])
45             ans = min(ans, d[i]);
46     }
47     cout<<n-ans<<endl;
48
49     return 0;
50 }

备注:

有思路后还是很清晰的一道题。最大空闲时间等价于求最少工作消耗时间。所以子问题是“以第i个任务为结尾的最少工作消耗时间”,在我的代码里用d[i]表示。状态怎样转移呢?引号内内容摘自洛谷题解,感觉说的非常清楚:

“把任务按照开始时间排序,以确保如果某一时刻无其他任务必须做一个。

f[i]=f[j]+cost(i) 仅当end(j)<start(i) 且 在区间(end(j),start(i))中无其他任务。

使用cnt(i)表示从1-i时刻有几个任务,如果cnt(a)==cnt(b)则说明a,b间无任务。”

一开始我居然不知道原问题的解是什么。。其实很简单啊,最后一个任务到工作时间结束之间没有其他任务开始的话,这就是一个完整的可行解。跟状态转移是一样的。

在我的代码里s数组就是回答中的cnt数组。我觉得cnt数组的设置和处理是十分巧妙的(已标黄)。它的递推过程也体现了一点动规的思想。

另外很巧妙的一点就是已标黄的“j=0”,这样一个小技巧就完美解决了在之前没有任务的情况下,最短消耗时间就是这个工作的消耗时间。

最后吐槽一点,我居然不小心在if后加了分号,并且因为这个问题查了一个小时orz

时间: 2024-10-10 20:28:09

1280 尼克的任务的相关文章

洛谷1280 尼克的任务

本题地址:http://www.luogu.org/problem/show?pid=1280 题目描述 尼克每天上班之前都连接上英特网,接收他的上司发来的邮件,这些邮件包含了尼克主管的部门当天要完成的全部任务,每个任务由一个开始时刻与一个持续时间构成.     尼克的一个工作日为N分钟,从第一分钟开始到第N分钟结束.当尼克到达单位后他就开始干活.如果在同一时刻有多个任务需要完戍,尼克可以任选其中的一个来做,而其余的则由他的同事完成,反之如果只有一个任务,则该任务必需由尼克去完成,假如某些任务开

洛谷OJ 1280 尼克的任务 线性DP

https://www.luogu.org/problem/show?pid=1280 1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 typedef pair<int,int> ii; 5 const int N=2e5+20; 6 const ll inf=2e15; 7 //ìaòa:??3?k,k<=1e4??1¤×÷????[s,t],?3ê±?ìóDè???&a

尼克的任务(洛谷 1280)

题目描述 尼克每天上班之前都连接上英特网,接收他的上司发来的邮件,这些邮件包含了尼克主管的部门当天要完成的全部任务,每个任务由一个开始时刻与一个持续时间构成. 尼克的一个工作日为N分钟,从第一分钟开始到第N分钟结束.当尼克到达单位后他就开始干活.如果在同一时刻有多个任务需要完戍,尼克可以任选其中的一个来做,而其余的则由他的同事完成,反之如果只有一个任务,则该任务必需由尼克去完成,假如某些任务开始时刻尼克正在工作,则这些任务也由尼克的同事完成.如果某任务于第P分钟开始,持续时间为T分钟,则该任务将

【洛谷1280】尼克的任务

我们发现这道题是有后效性的……前面的决策会对后面的产生影响…… 所以我们可以反向考虑 f [ i ] 表示第i分钟至第n分钟的最大空闲时间 理论上应该排个序,不过默认有序了…… 转移方程:如果该时间有任务开始,f [ i ] = max( f [ i ],f [ i+e [ i ] ]) 如果没有任务,f [ i ]=f [ i+1] +1 1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 usi

hdu 1280 前m大的数 哈希

前m大的数 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 10574    Accepted Submission(s): 3686 Problem Description 还记得Gardon给小希布置的那个作业么?(上次比赛的1005)其实小希已经找回了原来的那张数表,现在她想确认一下她的答案是否正确,但是整个的答案是很庞大的表,小

tyvj1034 尼克的任务

描述 尼克每天上班之前都连接上英特网,接收他的上司发来的邮件,这些邮件包含了尼克主管的部门当天要完成的全部任务,每个任务由一个开始时刻与一个持续时间构成.尼克的一个工作日为N分钟,从第一分钟开始到第N分钟结束.当尼克到达单位后他就开始干活.如果在同一时刻有多个任务需要完成,尼克可以任选其中的一个来做,而其余的则由他的同事完成,反之如果只有一个任务,则该任务必需由尼克去写成,假如某些任务开始时刻尼克正在工作,则这些任务也由尼克的同事完成.如果某任务于第P分钟开始,持续时间为T分钟,则该任务将在第P

杭电 1280 前m大的数

http://acm.hdu.edu.cn/showproblem.php?pid=1280 前m大的数 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 10382    Accepted Submission(s): 3614 Problem Description 还记得Gardon给小希布置的那个作业么?(上次比赛的1005)其实

[ACM 1280]码农总共睡了多少小时?

Description 给你一个码农的上床时间和起床时间,计算他总共睡了多少小时? Input 有多组测试数据 每组一行,为上床时间和起床时间,中间一个空格隔开 Output 对于每组数据,输出码农总共睡觉的时间t(分钟) 当然 0<=t<24*60 Sample Input 01:00 08:00 23:00 08:00 Sample Output 420 540 #include<algorithm> #include<iostream> #include<s

P1280 尼克的任务

题目描述 尼克每天上班之前都连接上英特网,接收他的上司发来的邮件,这些邮件包含了尼克主管的部门当天要完成的全部任务,每个任务由一个开始时刻与一个持续时间构成. 尼克的一个工作日为N分钟,从第一分钟开始到第N分钟结束.当尼克到达单位后他就开始干活.如果在同一时刻有多个任务需要完戍,尼克可以任选其中的一个来做,而其余的则由他的同事完成,反之如果只有一个任务,则该任务必需由尼克去完成,假如某些任务开始时刻尼克正在工作,则这些任务也由尼克的同事完成.如果某任务于第P分钟开始,持续时间为T分钟,则该任务将