【bzoj2336】[HNOI2011]任務調度

題目鏈接

Description

有 N 個任務和兩臺機器 A 與 B。每個任務都需要既在機器 A 上執行,又在機器 B 上執行,第 i 個任務需要在機器 A 上執行時間 Ai,且需要在機器 B 上執行時間 Bi。最終的目標是所有任務在 A 和 B 上都執行完,且希望執行完所有任務的總時間儘量少。當然問題沒有這麼簡單,有些任務對於先在機器 A 上執行還是先在機器 B 上執行有一定的限制。據此可將所有任務分爲三類:
1.任務必須先在機器 A 上執行完然後再在機器 B 上執行。
2.任務必須先在機器 B 上執行完然後再在機器 A 上執行。
3.任務沒有限制,既可先在機器 A 上執行,也可先在機器 B 上執行。
現在給定每個任務的類別和需要在機器A和機器B上分別執行的時間,問使所有任務都能按規定完成所需要的最少總時間是多少。

Input

從文件input.txt中讀入數據,輸入文件的第一行只有一個正整數N(1≤N≤20),表示任務的個數。接下來的N行,每行是用空格隔開的三個正整數Ti, Ai, Bi(1≤Ti≤3, 1≤Ai, Bi≤1000),分別表示第i個任務的類別(類別1, 2, 3的定義如上)以及第i個任務需要在機器A和機器B上分別執行的時間。

Output

輸出文件 output.txt 僅包含一個正整數,表示所有任務都執行完所需要的最少總時

Sample Input

3
3 5 7
1 6 1
2 2 6
14

Sample Output

14

Hint

樣例解釋:一種最優任務調度方案爲:機器A上執行的各任務依次安排如下:任務1(0 - 5), 任務2(5 - 11), 任務3(11 - 13);機器B上執行的各任務依次安排如下:任務3(0 - 6), 任務 1(6 - 13), 任務2(13 - 14),這樣,所有任務都執行完所需要的總時間爲14。

題解

乖乖,隨機化。
驚了,還以爲是DP。
枚舉每個3類型到底是1類型還是2類型,然後所有1類型按b時間從大到小排序,所有2類型按a時間從大到小排序,先貪心一下現在的答案。再隨機交換一下做任務的順序,如果更優就更換,如果不優就不換,就這樣。

#include<bits/stdc++.h>
using namespace std;

const int N = 30, inf = 0x3f3f3f3f;

int n, a[N], b[N], t[N];
int stk1[N], top1, stk2[N], top2;
bool wh[N];
int ans = inf;

bool cmp1(int p, int q){
    if(b[p] == b[q]) return a[p] < a[q];
    return b[p] > b[q];
}

bool cmp2(int p, int q){
    if(a[p] == b[q]) return b[p] < b[q];
    return a[p] > a[q];
}

void init(){
    scanf("%d", &n);
    for(int i = 1; i <= n; i++)
        scanf("%d%d%d", &t[i], &a[i], &b[i]);
}

int calc(){
    int sa = 0, sb = 0, ret = 0;
    for(int i = 1; i <= top2; i++) sb += b[stk2[i]];
    for(int i = 1; i <= top1; i++){
        sa += a[stk1[i]];
        if(sa < sb) sb += b[stk1[i]];
        else sb = sa + b[stk1[i]];
    }
    ret = max(sa, sb);
    sa = sb = 0;
    for(int i = 1; i <= top1; i++) sa += a[stk1[i]];
    for(int i = 1; i <= top2; i++){
        sb += b[stk2[i]];
        if(sb < sa) sa += a[stk2[i]];
        else sa = sb + a[stk2[i]];
    }
    return max(ret, max(sa, sb));
}

void solve(){
    top1 = top2 = 0;
    for(int i = 1; i <= n; i++)
        if(wh[i]) stk2[++top2] = i; else stk1[++top1] = i;
    sort(stk1+1, stk1+top1+1, cmp1);
    sort(stk2+1, stk2+top2+1, cmp2);
    int ret = calc(), t = 2000, a1, a2, b1, b2, tmp;
    while(t--){
        if(top1)
            swap(stk1[a1 = rand()%top1+1], stk1[a2 = rand()%top1+1]);
        if(top2)
            swap(stk2[b1 = rand()%top2+1], stk2[b2 = rand()%top2+1]);
        tmp = calc();
        if(tmp < ret) ret = tmp;
        else{
            if(top1) swap(stk1[a1], stk1[a2]);
            if(top2) swap(stk2[b1], stk2[b2]);
        }
    }
    if(ret < ans) ans = ret;
}

void dfs(int k){
    if(k > n) solve();
    else
        switch(t[k]){
            case 1: wh[k] = 0; dfs(k + 1); break;
            case 2: wh[k] = 1; dfs(k + 1); break;
            case 3: wh[k] = 0; dfs(k + 1); wh[k] = 1; dfs(k + 1); break;
        }
}

void work(){
    dfs(1);
    printf("%d\n", ans);
}

int main(){
    srand(10100619);
    init();
    work();
    return 0;
}
發佈了155 篇原創文章 · 獲贊 9 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章