【贪心+堆优化】任务时间表(task.cpp/pas)

 

任务时间表(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,1≤i≤n,1≤ di≤n,即要求任务i在时间di之前结束;

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

若按时完成则无惩罚。

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

 

输入文件(task.in):

第一行是正整数n(1≤n≤500),表示任务数;

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

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

 

输出文件(task.out):

最小的总误时惩罚数。

 

Sample Input Case 1:

7

4 2 4 3 1 4 6

70 60 50 40 30 20 10

 

Sample Output Case 1:

50

===========================

原来做过一道类似的题目

==============================

type
  node=record
         d,w:longint;
       end;
var
  n:longint;
  ti:array[1..500]of node;
  dui:array[1..500]of longint;
  dui_s:longint;
procedure init;
begin
  assign(input,'task.in');
  assign(output,'task.out');
  reset(input); rewrite(output);
end;

procedure terminate;
begin
  close(input); close(output);
  halt;
end;

procedure qsort(s,t:Longint);
var
  i,j:longint;
  x,tem:node;
begin
  i:=s; j:=t;
  x:=ti[(s+t)shr 1];
  repeat
    while (x.d<ti[j].d) or ((x.d=ti[j].d)and(x.w<ti[j].w)) do dec(j);
    while (ti[i].d<x.d) or ((x.d=ti[i].d)and(ti[i].w<x.w)) do inc(i);
    if i<=j then begin tem:=ti[i]; ti[i]:=ti[j]; ti[j]:=tem; inc(i); dec(j); end;
  until i>j;
  if i<t then qsort(i,t);
  if s<j then qsort(s,j);
end;

procedure adjust(k:longint);
var
  r:longint;
  tem:longint;
begin
  r:=k shr 1;
  while (r>0)and(ti[dui[r]].w<ti[dui[k]].w) do
    begin
      tem:=dui[r]; dui[r]:=dui[k]; dui[k]:=tem;
      k:=r; r:=k shr 1;
    end;
end;

procedure shift(r,n:longint);
var
  k:longint;
  tem:longint;
begin
  k:=r*2;
  if (k+1<=n)and(ti[dui[k+1]].w>ti[dui[k]].w) then inc(k);
  while (k<=n)and(ti[dui[k]].w>ti[dui[r]].w) do
    begin
      tem:=dui[k];  dui[k]:=dui[r]; dui[r]:=tem;
      r:=k;
      k:=r*2;
      if (k+1<=n)and(ti[dui[k+1]].w>ti[dui[k]].w) then inc(k);
    end;
end;

procedure main;
var
  i:longint;
  t:longint;
  num:longint;
  ans,ans_t:longint;
begin
  readln(n);
  ans:=0;
  for i:=1 to n do read(ti[i].d);
  for i:=1 to n do begin read(ti[i].w); ans:=ans+ti[i].w; end;
  qsort(1,n);
  t:=ti[n].d;
  dui_s:=1;
  dui[1]:=n;
  num:=n-1;
  ans_t:=0;
  for i:=t downto 1 do
    begin
      while (num>=1)and(ti[num].d=i) do
        begin
          inc(dui_s);
          dui[dui_s]:=num;
          adjust(dui_s);
          dec(num);
        end;
      if dui_s>=1 then
        begin
          inc(ans_t,ti[dui[1]].w);
          dui[1]:=dui[dui_s];
          dec(dui_s);
          shift(1,dui_s);
        end;
    end;
  writeln(ans-ans_t);
end;

begin
  init;
  main;
  terminate;
end.


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值