P1113 雑用(トポロジカルソートまたはメモリバックトラッキング)

トピックの説明

John農場では牛の乳搾りの前にやらなければならない雑事がたくさんあり、それぞれの雑務が完了するまでにある程度の時間がかかります。たとえば、牛を集め、牛舎に追い込み、牛の乳房を掃除し、その他の仕事をしなければなりません。より多くの母乳を搾るための時間を確保できるように、すべての家事をできるだけ早く終わらせることが重要です。もちろん、他の家事が完了するまで実行できない家事もあります。例: 牛を牛舎に追い込んだ後にのみ乳房の洗浄を開始できます。乳房を洗浄する前に牛の乳を搾ることはできません。これらのタスクを、この作業を完了するための準備と呼びます。準備作業を必要としない雑用が少なくとも 1 つあり、最も早く開始できるタスクが雑用 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

タイトルの意味:

次のステップに進む前に、前のタスクを完了する必要があります。タスクは同時に実行できます。同時に実行する最大のタスクを見つけるために、greedy を使用します。

解析:

解決策 1:

dfs メモリ バックトラッキング アルゴリズムを使用すると、最後のポイントに到達したときに、それが目的のタスクである必要があり、時間を追加する必要があります。

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
const int N = 10010;
int f[N];
int time1[N];
vector<int> a[N];
int dfs(int x) {
	if (f[x]) return f[x];//该节点已经遍历过了,减枝
	for (int i = 0; i < a[x].size(); i++) {
		f[x] = max(f[x], dfs(a[x][i])); //说有子集中最大的节点
	}
	f[x] += time1[x]; // 加上自己需要的时间
	return f[x];
}
int main() {
	
	int n;
	cin >> n;
	for (int i = 0; i < n; i++) {
		int x, y,z;
		cin >> x >> y >> z;
		time1[x] = y;
		while(z != 0){
			a[z].push_back(x);// 只有完成z 后才能完成 x 所以有z -> x的边
			scanf("%d", &z);
		}
	}

	int ans = 0;
	for (int i = 1; i <= n; i++) {
		ans = max(ans, dfs(i));
	}
	cout << ans<<endl;
	return 0;
}

解決策 2:

キュー レコード、トポロジカル ソートを使用し、入次数 0 のポイントをキューにプッシュします。

#include<iostream>
#include<vector>
#include<algorithm>
#include<queue>
using namespace std;
const int N = 10010;
int f[N];
int time1[N];
vector<int> a[N];
int in[N];
int main() {
	queue<int> q;
	int n;
	cin >> n;
	for (int i = 0; i < n; i++) {
		int x, y,z;
		cin >> x >> y >> z;
		time1[x] = y;
		while(z != 0){
			a[z].push_back(x);// 只有完成z 后才能完成 x 所以有z -> x的边
			scanf("%d", &z);
			in[x]++;
		}
	}

	int ans = 0;
	for (int i = 1; i <= n; i++) {
		if (in[i] == 0) {
			q.push(i);
			f[i] = time1[i];//记录需要的时间
		}
	}

	while (!q.empty()) {
		int pro = q.front();
		q.pop();
		for (int i = 0; i < a[pro].size(); i++) {
			int u = a[pro][i];
			in[u]--;
			if (in[u] == 0) q.push(u); //入度为0
			f[u] = max(f[u], f[pro]+time1[u]);//到达这个点中最大的时间
		}
	}
	for (int i = 1; i<= n; i++) {
		ans = max(ans, f[i]);
	}
	cout << ans<<endl;
	return 0;
}

おすすめ

転載: blog.csdn.net/zhi6fui/article/details/129633336