用動態規劃秒掉一道拓樸排序提

題目如下

題目描述

John的農場在給奶牛擠奶前有很多雜務要完成,每一項雜務都需要一定的時間來完成它。比如:他們要將奶牛集合起來,將他們趕進牛棚,爲奶牛清洗乳房以及一些其它工作。儘早將所有雜務完成是必要的,因爲這樣纔有更多時間擠出更多的牛奶。當然,有些雜務必須在另一些雜務完成的情況下才能進行。比如:只有將奶牛趕進牛棚才能開始爲它清洗乳房,還有在未給奶牛清洗乳房之前不能擠奶。我們把這些工作稱爲完成本項工作的準備工作。至少有一項雜務不要求有準備工作,這個可以最早着手完成的工作,標記爲雜務1。John有需要完成的n個雜務的清單,並且這份清單是有一定順序的,雜務k(k>1)的準備工作只可能在雜務1至k−1中。

寫一個程序從1到n讀入每個雜務的工作說明。計算出所有雜務都被完成的最短時間。當然互相沒有關係的雜務可以同時工作,並且,你可以假定John的農場有足夠多的工人來同時完成任意多項任務。

輸入格式

第1行:一個整數n,必須完成的雜務的數目(3 ≤n≤10,000);

第2至(n+1)行: 共有n行,每行有一些用1個空格隔開的整數,分別表示:

* 工作序號(1至n,在輸入文件中是有序的);

* 完成工作所需要的時間(1≤len≤100);

* 一些必須完成的準備工作,總數不超過100個,由一個數字0結束。有些雜務沒有需要準備的工作只描述一個單獨的0,整個輸入文件中不會出現多餘的空格。

輸出格式

一個整數,表示完成所有雜務所需的最短時間。

輸入輸出樣例

輸入 #1複製

7
1 5 0
2 2 1 0
3 3 2 0
4 6 1 0
5 1 2 4 0
6 8 2 4 0
7 4 3 5 6 0

輸出 #1複製

23

思路分析一

拓樸排序:

看到在..前提下...才能去做,,,, ,顯然是拓樸排序題,只要在每個節點進隊列的時候計算所需時間即可

顯然每個結點所需的時間爲:所有準備工作最大的時間+自身完成所需的時間(即木桶效應)

OK,思路就是這麼簡單,直接上代碼,

沒什麼可說的.拓樸排序的模板,這裏採用了鄰接矩陣

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

const int MAX = 5e4+5;
const int INF = 0x7fffffff;

int M,N;

struct Work{
    int len,index;
    int inDegree;
    int res;
    vector<int> pre;
    vector<int> next;
}work[MAX];

void topoSort() {
    queue<Work> queue;
    for (int i = 1; i <= N; ++i) {
        if(work[i].inDegree==0) {
            work[i].res=work[i].len;
            queue.push(work[i]);
        }
    }

    while (!queue.empty()) {
        Work root = queue.front();
        queue.pop();
        for (int i = 0; i < root.next.size(); ++i) {
            work[root.next[i]].inDegree--;
            if(work[root.next[i]].inDegree==0) {
                int t = 0;
                for (int j = 0; j < work[root.next[i]].pre.size(); ++j) {
                    t = max(t,work[work[root.next[i]].pre[j]].res);
                }
                work[root.next[i]].res = t+work[root.next[i]].len;
                queue.push(work[root.next[i]]);
            }
        }
    }
}

int main() {
    cin >> N;
    for (int i = 1; i <= N; ++i) {
        int x,condition;
        cin >> x;cin >> work[x].len;
        work[x].index=x;
        while (cin >> condition,condition) {
            work[x].inDegree++;
            work[x].pre.push_back(condition);
            work[condition].next.push_back(x);
        }
    }
    topoSort();
    int res = 0;
    for (int i = 1; i <= N; ++i) {
        res = max(work[i].res,res);
    }
    cout << res << endl;
}

動態規劃

思路和之前一樣,只要多想一步,就能想到.

狀態就是每個結點完成所需的時間,顯然它只取決於它自身的準備工作

OK,直接上代碼.

#include<iostream> 
#include<cstdio> 
using namespace std;
int main(){ 
    int t[10001],n,ans=0,k,num,ti,x,y,i;//定這麼一大坨東西 
    scanf("%d",&n);
    for(i=1;i<=n;i++){ 
        scanf("%d%d",&k,&ti);
        t[k]=ti;
        scanf("%d",&x);
        while(x!=0){ 
               t[k]=max(t[k],ti+t[x]);
               ans=max(ans,t[k]);//更新操作
            scanf("%d",&x);
        } 
    } 
    printf("%d",ans);
    return 0;
} 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章