您的位置:首页 > 理论基础

vijos1534 高性能计算机

2018-01-11 00:44 204 查看
http://www.elijahqi.win/2018/01/11/vijos1534-%e9%ab%98%e6%80%a7%e8%83%bd%e8%ae%a1%e7%ae%97%e6%9c%ba/

背景

WinterCamp 2001 高性能计算机(hpc)

Description:Official

Data:Official

Program:Unknown

描述

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

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

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

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

tiAt_i^A

tiA​和

tiB (i=1,2,…,p)t_i^B~(i=1,2,…,p)

tiB​ (i=1,2,…,p)分别表示节点i转入工作状态A和工作状态B的启动时间(单位:ns)。

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

若节点i连续处理x个A类子任务,则对应的执行时间为:

t=kiAx2t=k_i^Ax^2

t=kiA​x2

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

t=kiBx2t=k_i^Bx^2

t=kiB​x2

其中,

kiAk_i^A

kiA​和

kiBk_i^B

kiB​是系数,单位是ns,

i=1,2,…,pi=1,2,…,p

i=1,2,…,p。

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

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

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

格式

输入格式

第一行是对计算任务的描述,包括两个正整数

nAn_A

nA​和

nBn_B

nB​,分别是A类和B类子任务的数目,两个整数之间由一个空格隔开。

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

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

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

tiA tiB kiA kiBt_i^A~t_i^B~k_i^A~k_i^B

tiA​ tiB​ kiA​ kiB​

输出格式

只有一行,包含有一个正整数,即从各节点开始计算到任务完成所用的时间。

样例1

样例输入1

5 5

3

15 10 6 4

70 100 7 2

30 70 1 6

Copy

样例输出1

93

Copy

限制

本题一共6个测试点,第1、2、3点10分,第4、5点20分,第6点30分。

由于题目没给时限,本人视实际情况,定第1、2、3点时限1s,第4点时限2s,第5、6点时限3s。

提示

1≤nA≤60,1≤nB≤60 1 \le n_A \le 60, 1 \le n_B \le 60

1≤nA​≤60,1≤nB​≤60

1≤p≤20 1 \le p \le 20

1≤p≤20

1≤tA≤1000,1≤tB≤1000,1≤kA≤50,1≤kB≤50 1 \le t_A \le 1000, 1 \le t_B \le 1000, 1 \le k_A \le 50, 1 \le k_B \le 50

1≤tA​≤1000,1≤tB​≤1000,1≤kA​≤50,1≤kB​≤50

来源

WinterCamp 2001 高性能计算机(hpc)

Description:Official

Data:Official

Program:Unknown

自己菜菜的啊 观摩icefox巨佬题解 可知 我们现在其实相当于分成了两个子任务待解决 1、针对每个点节点计算出 t[0/1][i][j]表示 最后一个做的是A 还是B 然后我已经做了i个A j个B了的最小时间花费是多少 2、dp[now][i][j]表示 现在处于第now个节点 已经处理了i个A j个B真正的最小时间花费

t[0][i][j]=min{t[1][i-k][j]+ta[x]+ka[x]*k*k}

t[1][i][j]=min{t[0][i][j-k]+tb[x]+kb[x]*k*k}.

边界条件为t[0][0][0]=t[1][0][0]=0.注意给t清最大值。

再记一个tim[x][i][j]数组,表示第x个节点完成i个A,j个B所需的最短时间。

解决第二个问题:用dp[x][i][j]表示前x个节点完成i个A任务和j个B任务的最短实际运行时间。则

dp[x][i][j] = min{max(dp[x-1][i-ki][j-kj],tim[x][ki][kj])}

边界条件为dp[1][i][j]=tim[1][i][j]。

#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 66
using namespace std;
int t[2]

,dp[22]

,tim[22]

,na,nb,n,ta
,tb
,ka
,kb
;
inline char gc(){
static char now[1<<16],*S,*T;
if (T==S){T=(S=now)+fread(now,1,1<<16,stdin);if (T==S) return EOF;}
return *S++;
}
inline int read(){
int x=0;char ch=gc();
while(ch<'0'||ch>'9') ch=gc();
while(ch<='9'&&ch>='0') x=x*10+ch-'0',ch=gc();return x;
}
int main(){
freopen("vijos1534.in","r",stdin);
na=read();nb=read();n=read();
for (int i=1;i<=n;++i) ta[i]=read(),tb[i]=read(),ka[i]=read(),kb[i]=read();
for (int i=1;i<=n;++i){
memset(t,0x3f,sizeof(t));t[0][0][0]=t[1][0][0]=0;
for (int ii=0;ii<=na;++ii)
for (int j=0;j<=nb;++j){
for (int z=1;z<=ii;++z) t[0][ii][j]=min(t[0][ii][j],t[1][ii-z][j]+ta[i]+ka[i]*z*z);
for (int z=1;z<=j;++z) t[1][ii][j]=min(t[1][ii][j],t[0][ii][j-z]+tb[i]+kb[i]*z*z);
tim[i][ii][j]=min(t[0][ii][j],t[1][ii][j]);
}
}memset(dp,0x3f,sizeof(dp));
for (int i=0;i<=na;++i)
for (int j=0;j<=nb;++j) dp[1][i][j]=tim[1][i][j];
for (int now=2;now<=n;++now)
for (int i=0;i<=na;++i)
for (int j=0;j<
e9bf
;=nb;++j)
for (int ki=0;ki<=i;++ki)
for (int kj=0;kj<=j;++kj)
dp[now][i][j]=min(dp[now][i][j],max(dp[now-1][i-ki][j-kj],tim[now][ki][kj]));
printf("%d",dp
[na][nb]);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: