1. 程式人生 > >【WC2001】【cogs358】高性能計算機(動態規劃)

【WC2001】【cogs358】高性能計算機(動態規劃)

結束 輸入輸出 計算機 stdout 所有 主存 時間 span 要花

【WC2001】【cogs358】高性能計算機(動態規劃)

##題面

【問題描述】

現在有一項時間緊迫的工程計算任務要交給你——國家高性能並行計算機的主管工程師——來完成。為了盡可能充分發揮並行計算機的優勢,我們的計算任務應當劃分成若幹個小的子任務。

這項大型計算任務包括A和B兩個互不相關的較小的計算任務。為了充分發揮並行計算機的運算能力,這些任務需要進行分解。研究發現,A和B都可以各自劃分成很多較小的子任務,所有的A類子任務的工作量都是一樣的,所有的B類子任務也是如此(A和B類的子任務的工作量不一定相同)。A和B兩個計算任務之間,以及各子任務之間都沒有執行順序上的要求。

這臺超級計算機擁有p個計算節點,每個節點都包括一個串行處理器、本地主存和高速cache。然而由於常年使用和不連貫的升級,各個計算節點的計算能力並不對稱。一個節點的計算能力包括如下幾個方面:

  1. 就本任務來說,每個節點都有三種工作狀態:待機、A類和B類。其中,A類狀態下執行A類任務;B類狀態下執行B類任務;待機狀態下不執行計算。所有的處理器在開始工作之前都處於待機狀態,而從其它的狀態轉入A或B的工作狀態(包括A和B之間相互轉換),都要花費一定的啟動時間。對於不同的處理節點,這個時間不一定相同。用兩個正整數tiA和tiB (i=1,2,...,p)分別表示節點i轉入工作狀態A和工作狀態B的啟動時間(單位:ns)。

  2. 一個節點在連續處理同一類任務的時候,執行時間——不含狀態轉換的時間——隨任務量(這一類子任務的數目)的平方增長,即:
    若節點i連續處理x個A類子任務,則對應的執行時間為:t=kiAx2

    類似的,若節點i連續處理x個B類子任務,對應的執行時間為:t=kiBx2
    其中,kiA和kiB是系數,單位是ns,i=1,2,...,p。

任務分配必須在所有計算開始之前完成,所謂任務分配,即給每個計算節點設置一個任務隊列,隊列由一串A類和B類子任務組成。兩類子任務可以交錯排列。

計算開始後,各計算節點分別從各自的子任務隊列中順序讀取計算任務並執行,隊列中連續的同類子任務將由該計算節點一次性讀出,隊列中一串連續的同類子任務不能被分成兩部分執行。

【編程任務】

現在需要你編寫程序,給這 p 個節點安排計算任務,使得這個工程計算任務能夠盡早完成。假定任務安排好後不再變動,而且所有的節點都同時開始運行,任務安排的目標是使最後結束計算的節點的完成時間盡可能早。

【輸入輸出】

輸入文件名是 hpc.in 。

文件的第一行是對計算任務的描述,包括兩個正整數 nA 和 nB,分別是 A 類和 B 類子任務的數目,兩個整數之間由一個空格隔開。

文件的後面部分是對此計算機的描述:

文件第二行是一個整數 p ,即計算節點的數目。

隨後連續的 p 行按順序分別描述各個節點的信息,第 i 個節點由第 i+2 行描述,該行包括下述四個正整數(相鄰兩個整數之間有一個空格):

tiA tiB kiA kiB

輸出文件名是 hpc.out 。其中只有一行,包含有一個正整數,即從各節點開始計算到任務完成所用的時間。

【樣例】

設輸入文件hpc.in為
5 5
3
15 10 6 4
70 100 7 2
30 70 1 6

對應的輸出文件 hpc.out 為

93

【數據說明】

1 ≤ nA ≤ 60

1 ≤ nB ≤ 60

1 ≤ p ≤ 20

1 ≤ tA ≤ 1000

1 ≤ tB ≤ 1000

1 ≤ kA ≤ 50

1 ≤ kB ≤ 50

題解

這題不是很難吧。。。
首先考慮做一次DP
預處理出對於每一個節點執行\(i\)個A任務,\(j\)個B任務的最短時間
然後就是一個很簡單的DP了
也就是做兩次DP

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<set>
#include<map>
#include<vector>
#include<queue>
using namespace std;
inline int read()
{
    int x=0,t=1;char ch=getchar();
    while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
    if(ch=='-')t=-1,ch=getchar();
    while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
    return x*t;
}
int f1[25][65][65];
int f2[25][65][65];
int p,ta[25],tb[25],ka[25],kb[25];
int na,nb;
//f1[p][i][j]表示第p個節點執行i個A任務,j個B任務的最短時間
void DP1()
{
    for(int a=1;a<=p;++a)
    {
        int F[2][65][65];
        memset(F,31,sizeof(F));
        F[1][0][0]=F[0][0][0]=0;
        for(int i=0;i<=na;++i)
            for(int j=0;j<=nb;++j)
            {
                for(int k=1;k<=i;++k)F[0][i][j]=min(F[0][i][j],F[1][i-k][j]+ka[a]*k*k+ta[a]);
                for(int k=1;k<=j;++k)F[1][i][j]=min(F[1][i][j],F[0][i][j-k]+kb[a]*k*k+tb[a]);
                f1[a][i][j]=min(F[0][i][j],F[1][i][j]);
            }
    }
}
//f2[p][i][j]表示前p個節點執行i個A任務,j個B任務的最短時間
void DP2()
{
    memset(f2,31,sizeof(f2));
    for(int i=0;i<=na;++i)
        for(int j=0;j<=nb;++j)
            f2[1][i][j]=f1[1][i][j];
    for(int a=2;a<=p;++a)
    {
        for(int i=0;i<=na;++i)
            for(int j=0;j<=nb;++j)
                for(int k=0;k<=i;++k)
                    for(int l=0;l<=j;++l)
                        f2[a][i][j]=min(f2[a][i][j],max(f2[a-1][k][l],f1[a][i-k][j-l]));
    }
}
int main()
{
    freopen("hpc.in","r",stdin);
    freopen("hpc.out","w",stdout);
    na=read();nb=read();
    p=read();
    for(int i=1;i<=p;++i)ta[i]=read(),tb[i]=read(),ka[i]=read(),kb[i]=read();
    DP1();
    DP2();
    printf("%d\n",f2[p][na][nb]);
    return 0;
}

【WC2001】【cogs358】高性能計算機(動態規劃)