WC'2001HPC

高性能计算机

hpc.pas(exe)

hpc.in

hpc.out

【问题描述】

现在有一项时间紧迫的工程计算任务要交给你——国家高性能并行计算机的主管工程师——来完成。为了尽可能充分发挥并行计算机的优势,我们的计算任务应当划分成若干个小的子任务。

这项大型计算任务包括AB两个互不相关的较小的计算任务。为了充分发挥并行计算机的运算能力,这些任务需要进行分解。研究发现,AB都可以各自划分成很多较小的子任务,所有的A类子任务的工作量都是一样的,所有的B类子任务也是如此(AB类的子任务的工作量不一定相同)。AB两个计算任务之间,以及各子任务之间都没有执行顺序上的要求。

这台超级计算机拥有p个计算节点,每个节点都包括一个串行处理器、本地主存和高速cache。然而由于常年使用和不连贯的升级,各个计算节点的计算能力并不对称。一个节点的计算能力包括如下几个方面:

1. 就本任务来说,每个节点都有三种工作状态:待机、A类和B类。其中,A类状态下执行A类任务;B类状态下执行B类任务;待机状态下不执行计算。所有的处理器在开始工作之前都处于待机状态,而从其它的状态转入AB的工作状态(包括AB之间相互转换),都要花费一定的启动时间。对于不同的处理节点,这个时间不一定相同。用两个正整数和()分别表示节点i转入工作状态A和工作状态B的启动时间(单位:ns)。

2. 一个节点在连续处理同一类任务的时候,执行时间——不含状态转换的时间——随任务量(这一类子任务的数目)的平方增长,即:
若节点i连续处理xA类子任务,则对应的执行时间为

类似的,若节点i连续处理xB类子任务,对应的执行时间为:

其中,和是系数,单位是ns。。

任务分配必须在所有计算开始之前完成,所谓任务分配,即给每个计算节点设置一个任务队列,队列由一串A类和B类子任务组成。两类子任务可以交错排列。

计算开始后,各计算节点分别从各自的子任务队列中顺序读取计算任务并执行,队列中连续的同类子任务将由该计算节点一次性读出,队列中一串连续的同类子任务不能被分成两部分执行。

【编程任务】

现在需要你编写程序,给这p个节点安排计算任务,使得这个工程计算任务能够尽早完成。假定任务安排好后不再变动,而且所有的节点都同时开始运行,任务安排的目标是使最后结束计算的节点的完成时间尽可能早。

【输入输出】

输入文件名是hpc.in

文件的第一行是对计算任务的描述,包括两个正整数和,分别是A类和B类子任务的数目,两个整数之间由一个空格隔开。

文件的后面部分是对此计算机的描述:

文件第二行是一个整数p,即计算节点的数目。

随后连续的p行按顺序分别描述各个节点的信息,第i个节点由第i+2行描述,该行包括下述四个正整数(相邻两个整数之间有一个空格):

   

输出文件名是hpc.out。其中只有一行,包含有一个正整数,即从各节点开始计算到任务完成所用的时间。

【样例】

设输入文件hpc.in为

5 5

3

15 10 6 4

70 100 7 2

30 70 1 6

对应的输出文件hpc.out为

           93

-------------------------------------------------------------------------------------------------------------------
DP函数嵌套DP函数,这个思路不难想到,但毕竟是第一次见到,还是觉得很犀利~
ga[i,ma,mb]:=
min{gb[i,ma-pa,mb]+ta[i]+ka[i]*pa*pa|0<pa<=ma} (ma<>0)
inf     (ma=0,mb<>0)
0     (ma=0,mb=0)
gb[i,ma,mb]:=
min{ga[i,ma,mb-pb]+tb[i]+kb[i]*pb*pb|0<pb<=mb} (mb<>0)
inf     (mb=0,ma<>0)
0     (ma=0,mb=0)
g[i,ma,mb]:=min{ga[i,ma,mb],gb[i,ma,mb]}
f[i,ma,mb]:=
min{f[i-1,ma-pa,mb-pb]|0<=pa<=ma,0<=pb<=mb} (i>0)
inf (i=0,(ma<>0)or(mb<>0))
0 (i=0,ma=0,mb=0)
此外在存储上,f可以采取滚动数组优化,g也可以降到二维,由于数据内存占用不大,我只把Dp-g写到了Dp-f的内部,而没有采用滚动数组实现。
-------------------------------------------------------------------------------------------------------------------
代码:

var
   g,ga,gb:array[0..60,0..60] of longint;
   f:array[0..20,0..60,0..60] of longint;
   ta,tb,ka,kb:array[1..20] of longint;
   na,nb,p:longint;
function min(a,b:longint):longint; begin if a<b then exit(a) else exit(b); end;
function max(a,b:longint):longint; begin if a>b then exit(a) else exit(b); end;
procedure init;
var
   i:longint;
begin
     readln(na,nb);
     readln(p);
     for i:=1 to p do readln(ta[i],tb[i],ka[i],kb[i]);
end;
function ans:longint;
var
   i,ma,mb,pa,pb:longint;
begin
     {init}
     fillchar(f,sizeof(f),0);
     for ma:=0 to na do
     for mb:=0 to nb do
     f[0,ma,mb]:=maxlongint div 2;
     f[0,0,0]:=0;
     {dp}
     for i:=1 to p do begin
         {dp of g}
         fillchar(g,sizeof(g),0);
         fillchar(ga,sizeof(ga),0);
         fillchar(gb,sizeof(gb),0);
         for ma:=1 to na do begin
             ga[ma,0]:=ta[i]+ka[i]*ma*ma;
             gb[ma,0]:=maxlongint div 2;
             g[ma,0]:=ga[ma,0];
         end;
         for mb:=1 to nb do begin
             ga[0,mb]:=maxlongint div 2;
             gb[0,mb]:=tb[i]+kb[i]*mb*mb;
             g[0,mb]:=gb[0,mb];
         end;
         for ma:=1 to na do
         for mb:=1 to nb do begin
             ga[ma,mb]:=maxlongint div 2;
             for pa:=1 to ma do ga[ma,mb]:=min(ga[ma,mb],gb[ma-pa,mb]+ta[i]+ka[i]*pa*pa);
             gb[ma,mb]:=maxlongint;
             for pb:=1 to mb do gb[ma,mb]:=min(gb[ma,mb],ga[ma,mb-pb]+tb[i]+kb[i]*pb*pb);
             g[ma,mb]:=min(ga[ma,mb],gb[ma,mb]);
         end;
         {dp of f}
         for ma:=0 to na do
         for mb:=0 to nb do begin
             f[i,ma,mb]:=maxlongint div 2;
             for pa:=0 to ma do
             for pb:=0 to mb do
                 f[i,ma,mb]:=min(f[i,ma,mb],max(f[i-1,ma-pa,mb-pb],g[pa,pb]));
         end;
     end;
     ans:=f[p,na,nb];
     {end}
end;
procedure Debug;
var
   i,j,k:longint;
begin
     {f}
     for i:=0 to p do
     for j:=0 to na do
     for k:=0 to nb do
     writeln('f[',i,',',j,',',k,']=',f[i,j,k]);
     {ta}
     for i:=1 to p do writeln('ta[',i,']=',ta[i]);
     {tb}
     for i:=1 to p do writeln('tb[',i,']=',tb[i]);
     {na}
     for i:=1 to p do writeln('na[',i,']=',ka[i]);
     {nb}
     for i:=1 to p do writeln('nb[',i,']=',kb[i]);
end;
procedure main;
begin
     assign(input,'hpc.in');
     assign(output,'hpc.out');
     reset(input);
     rewrite(output);
     init;
     writeln(ans);
     {Debug;}
     close(input);
     close(output);
end;
begin
     main;
end.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值