【任务时间表】解题报告

来源:互联网 发布:高跟鞋推荐平价 知乎 编辑:程序博客网 时间:2024/06/09 17:29

3任务时间表(task.cpp/pas)


题目描述(Description):

一个单位时间任务是恰好需要一个单位时间完成的任务。给定一个单位时间任务的有限集S。关于S的一个时间表用于描述S中单位时间任务的执行次序。时间表中第1个任务从时间0开始执行直至时间1结束,第2个任务从时间1开始执行至时间2结束,…,第n个任务从时间n-1开始执行直至时间n结束。

具有截止时间和误时惩罚的单位时间任务时间表问题可描述如下。

(1)n个单位时间任务的集合S={1,2,,n}

(2)任务i的截止时间di,1in,1din,即要求任务i在时间di之前结束;

(3)任务i的误时惩罚wi,1in,即任务i未在时间di之前结束将招致wi的惩罚;

若按时完成则无惩罚。

现给定n个单位时间任务,各任务的截止时间di,各任务的误时惩罚wi,1in,编程对给定的S计算一个最优时间表,使得总误时惩罚达到最小。


输入文件(task.in):

第一行是正整数n1n500),表示任务数;

第二行有n个正整数,分别表示各任务的截止时间di1di500);

第三行有n个正整数,分别表示各任务的误时惩罚wi1wi1000)。


输出文件(task.out):

最小的总误时惩罚数。


SampleInput Case 1:

7

42 4 3 1 4 6

7060 50 40 30 20 10


SampleOutput Case 1:

50



这是做过的基本上一模一样的一道题,可是还是错了。原因是multimap错用成map了。

这道题我用的方法就是贪心的方法,倒着来贪心,最晚时刻能做的任务肯定做最晚时刻的任务,并做最优的。

向前一个时刻,就多出来一些选择,即当前时刻和后面时刻剩下来没做的任务,做最优的。

显然是一个小根堆。


这道题还有一个并查集的方法,即贪心,按照价值排序来选择,没选择一个任务,就从它最晚时间开始向前扫,找到第一个可以做的时刻,然后把区间合并。参见前两天的题

//#include <iostream>//using std::cout;//using std::cin;#include <cstdio>#include <map>using std::multimap;using std::make_pair;multimap<long,long> task;long n;const long oo = 0x7fff0000;long d[502];long w[502];long maxd = 0;struct node{long w;node* next;};node* tim[502];long tot = 0;void ins(long d,long w){node* tmp = new node;tmp->w = w;tmp->next = tim[d];tim[d] = tmp;}int main(){freopen("task.in","r",stdin);freopen("task.out","w",stdout);scanf("%ld",&n);for (long i=1;i<n+1;i++){scanf("%ld",d+i);maxd >?= d[i];}for (long i=1;i<n+1;i++){scanf("%ld",w+i);tot += w[i];}for (long i=1;i<n+1;i++){ins(d[i],-w[i]);}long ans = 0;for (long i=maxd;i>0;i--){node* ths = tim[i];while (ths){task.insert(make_pair(ths->w,ths->w));ths = ths->next;}if (!task.empty()){long ttt = task.begin()->first;ans += ttt;task.erase(task.begin());}}if (tot+ans<0) printf("0");else printf("%ld",tot+ans);return 0;}


原创粉丝点击