P1113 Tareas (clasificación topológica o retroceso de memoria)

Tema Descripción

JohnLa granja tiene muchas tareas que hacer antes de ordeñar las vacas y cada tarea requiere una cierta cantidad de tiempo para completarla. Por ejemplo: tienen que recoger las vacas, llevarlas al establo, limpiar las ubres de las vacas y algún otro trabajo. Es fundamental realizar todas las tareas lo antes posible para tener más tiempo para extraer más leche. Por supuesto, algunas tareas no se pueden realizar hasta que se hayan completado otras. Por ejemplo: solo puede comenzar a limpiar la ubre de la vaca después de llevarla al establo, y no puede ordeñar la vaca antes de limpiar la ubre. Nos referimos a estas tareas como preparativos para completar este trabajo. Hay al menos una tarea que no requiere trabajo de preparación y la tarea que se puede iniciar lo antes posible está marcada como Tarea 1. JohnHay una lista de n tareas que deben completarse, y esta lista tiene un orden determinado. La preparación de tareas k (k>1) solo es posible en las tareas 1 a k−1.

Escriba un programa que lea descripciones de trabajo para cada tarea del 1 al n. Calcule el tiempo mínimo para completar todas las tareas. Por supuesto, se pueden realizar tareas no relacionadas al mismo tiempo y se puede suponer que Johnla granja tiene suficientes trabajadores para realizar cualquier cantidad de tareas al mismo tiempo.

formato de entrada

Línea 1: un número entero n, el número de tareas que se deben realizar (3≤n≤10,000);

Líneas 2 a (n + 1): hay n líneas en total, y cada línea tiene algunos números enteros separados por 1 espacio, que representan respectivamente:

* Número de secuencia del trabajo (1 an, ordenado en el archivo de entrada);

* El tiempo necesario para completar el trabajo (1≤len≤100);

* Algunos trabajos preparatorios que deben completarse, el número total no supera los 100 y termina con un número 0. Algunas tareas no requieren trabajo preparatorio y solo describen un 0, y no aparecerán espacios adicionales en todo el archivo de entrada.

formato de salida

Un número entero que representa el tiempo mínimo necesario para completar todas las tareas.

Muestras de entrada y salida

Escriba #1 para copiar

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

salida #1 copia

23

Significado del título:

Debe completar las tareas anteriores antes de continuar con el siguiente paso y las tareas se pueden realizar al mismo tiempo. Usamos greedy para encontrar la tarea más grande para realizar al mismo tiempo.

Analizar gramaticalmente:

Solución 1:

Usando el algoritmo de retroceso de memoria dfs, cuando se llega al último punto, debe ser la tarea que desea y se debe agregar el tiempo.

#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;
}

Solución 2:

Utilice registros de cola, clasificación topológica y puntos de inserción con un grado de entrada de 0 en la cola.

#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;
}

Supongo que te gusta

Origin blog.csdn.net/zhi6fui/article/details/129633336
Recomendado
Clasificación