Algunos registros sobre las preguntas variantes de Dijkstra, siguiendo el cambio de plantilla de Dijkstra

Algunos registros sobre las preguntas variantes de Dijkstra, siguiendo el cambio de plantilla de Dijkstra

Antes escribí un pequeño resumen sobre la plantilla general tonta de Dijkstra. Más tarde, estaba haciendo algunas preguntas sobre las variantes del algoritmo de Dijkstra, y las encontré muy interesantes. Escribe un blog aquí para registrar dos de ellas. Por cierto, suelta la solución


Prefacio

Algunas de las preguntas parecen muy complicadas, pero de hecho, si entiendes el significado del título, después del resumen y simplificado, la plantilla casi se cambia.


一 、 HDU 1595 encuentra la más larga de la más corta

Enlace del título original

1. Contenido de la asignatura

Marica está muy enojada con Mirko porque encontró una nueva novia y ella busca venganza, como ella no vive en la misma ciudad, comenzó a prepararse para el largo viaje, sabemos por cada camino cuántos minutos se tarda en venir de uno. ciudad a otra.
Mirko escuchó en el automóvil que una de las carreteras está en reparación y que está bloqueada, pero no sabía exactamente qué carretera. Es posible venir de la ciudad de Marica a la de Mirko sin importar qué camino esté cerrado.
Marica viajará solo por caminos no bloqueados y viajará por la ruta más corta. Mirko quiere saber cuánto tiempo le llevará llegar a su ciudad en el peor de los casos, para asegurarse de que su novia esté fuera de la ciudad el tiempo suficiente. Escribe un programa que ayude a Mirko a descubrir cuál es el problema. el tiempo más largo en minutos que podría tomar Marica para llegar por la ruta más corta por caminos no bloqueados a su ciudad.

输入 要求 En
cada caso hay dos números en la primera fila, N y M, separados por un solo espacio, el número de pueblos y el número de carreteras entre los pueblos. 1 ≤ N ≤ 1000, 1 ≤ M ≤ N * (N-1) / 2. Las ciudades están marcadas con números del 1 al N, Mirko está ubicada en la ciudad 1 y Marica en la ciudad N.
En las siguientes líneas M hay tres números A, B y V, separados por comas. 1 ≤ A, B ≤ N, 1 ≤ V ≤ 1000.Estos números significan que hay una carretera de doble sentido entre las ciudades A y B, y que se puede cruzar en V minutos.

输出 要求
En la primera línea del archivo de salida, escriba el tiempo máximo en minutos que podría tardar Marica en llegar a Mirko.

Caso de uso de entrada

5 6
1 2 4
1 3 3
2 3 1
2 4 4
2 5 7
4 5 1

6 7
1 2 1
2 3 4
3 4 4
4 6 4
1 5 5
2 5 2
5 6 5

5 7
1 2 8
1 4 10
2 3 9
2 4 10
2 5 1
3 4 7
3 5 10

Caso de uso de salida

11
13
27

2. Ideas para la resolución de problemas

De acuerdo con el significado de la pregunta, primero encuentre el camino más corto en condiciones normales, luego enumere y elimine los bordes en el camino más corto normal, y luego registre cada camino más corto después de que se elimine el camino, y finalmente calcule el peor de los casos

el código se muestra a continuación:

#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int inf=1e7+10;
int n,m,a,b,v;
int map[1010][1010];
int dis[1010],mark[1010],vis[1010];
void dijkstra(int x)
{
    
    
	int minium,u;
	for(int i=1;i<=n;i++)
		dis[i]=inf;
	dis[1]=0;
	memset(vis,0,sizeof(vis));
	for(int i=1;i<n;i++)
	{
    
    
		minium=inf;
		for(int j=1;j<=n;j++)
		{
    
    
			if(vis[j]==0 && dis[j]<minium)
			{
    
    
				minium=dis[j];//记录当前最小值
				u=j;//记录当前dis[]中最小的元素的下标
			}
		}
		if(minium==inf)//无法达到
			return;
		vis[u]=1;
		for(int k=1;k<=n;k++)
		{
    
    
			if(dis[k]>dis[u]+map[u][k])
			{
    
    
				dis[k]=dis[u]+map[u][k];
				if(x)
					mark[k]=u;//记录最终dis[]中最小元素的下标
			}
		}
	}
}
int main()
{
    
    
	int maxn,temp;
	while(cin>>n>>m)
	{
    
    
		for(int i=1;i<=n;i++)
        {
    
    
			for(int j=1;j<=n;j++)
			{
    
    
				if(i==j)
					map[i][j]=0;
				else
					map[i][j]=inf;
			}
        }//构图
		memset(mark,0,sizeof(mark));
		for(int i=1;i<=m;i++)
		{
    
    
			cin>>a>>b>>v;//城市,穿越时间
			if(map[a][b]>v)
				map[a][b]=map[b][a]=v;//这是双向图,距离赋值
		}
		dijkstra(1);
		maxn=dis[n];
		for(int i=n;i!=1;i=mark[i])
		{
    
    
			temp=map[i][mark[i]];
			map[i][mark[i]]=map[mark[i]][i]=inf;//封路
			dijkstra(0);
			maxn=max(maxn,dis[n]);//记录封路后每一次的最短路
			map[i][mark[i]]=map[mark[i]][i]=temp;
		}//依次堵住一条路,求被堵后的最长路径
		cout<<maxn<<endl;
	}
	return 0;
}

Dos, POJ 2253 Frogger

Enlace del título original

1. Contenido de la asignatura

Freddy Frog está sentado sobre una piedra en medio de un lago. De repente se da cuenta de que Fiona Frog está sentada en otra piedra. Él planea visitarla, pero como el agua está sucia y llena de protector solar de turistas, quiere evitar nadar y en su lugar alcanzarla saltando.
Desafortunadamente, la piedra de Fiona está fuera de su rango de salto. Por eso Freddy considera utilizar otras piedras como paradas intermedias y llegar hasta ella mediante una secuencia de varios pequeños saltos.
Para ejecutar una secuencia dada de saltos, el rango de salto de una rana obviamente debe ser al menos tan largo como el salto más largo que ocurra en la secuencia.
La distancia de la rana (los humanos también la llaman distancia minimax) entre dos piedras, por lo tanto, se define como el rango de salto mínimo necesario sobre todos los caminos posibles entre las dos piedras.

Se le dan las coordenadas de la piedra de Freddy, la piedra de Fiona y todas las demás piedras del lago. Tu trabajo consiste en calcular la distancia de la rana entre la piedra de Freddy y la de Fiona.

输入 要求
La entrada contendrá uno o más casos de prueba. La primera línea de cada caso de prueba contendrá el número de piedras n (2 <= n <= 200). Las siguientes n líneas contienen cada una dos enteros xi, yi (0 <= xi, yi <= 1000) que representan las coordenadas de la piedra #i. La piedra n. ° 1 es la piedra de Freddy, la piedra n. ° 2 es la piedra de Fiona, las otras n-2 están desocupadas. Hay una línea en blanco después de cada caso de prueba. La entrada se termina con un valor de cero (0) para n.

输出 要求
Para cada caso de prueba, imprima una línea que diga "Escenario #x" y una línea que diga "Distancia de rana = y" donde x se reemplaza por el número de caso de prueba (se numeran desde 1) e y se reemplaza por el valor real apropiado número, impreso a tres decimales. Ponga una línea en blanco después de cada caso de prueba, incluso después del último.

Caso de uso de entrada

2
0 0
3 4

3
17 4
19 4
18 5

0

Caso de uso de salida

Scenario #1
Frog Distance = 5.000

Scenario #2
Frog Distance = 1.414

2. Ideas para la resolución de problemas

La clave está en el minimax del título, si lo entiendes, sabrás lo que significa. En primer lugar, una de las condiciones ocultas de este problema es un gráfico de dos vías, y luego se puede entender que si hay dos caminos 1 (4) 5 (3) 2 que representan el borde entre 1 y 5, el tiempo empleado es entre 4, 2 y 5. La distancia del borde es 3, entonces el rango de salto de la ruta es 4 (es decir, la distancia de 1 a 5 es naturalmente mayor que 2 a 5, y el tiempo de 1 a 5 es menor que 2 a 5, que es el llamado minimax). Un camino es 1 (6) 4 (1) 2. De manera similar, el rango de salto de este camino es 6, y los rangos de salto de dos caminos son 4 y 6, respectivamente. De manera similar, el rango de salto mínimo que requerimos es 4. Comprender Entonces empieza a resolver el problema.

el código se muestra a continuación:

#include<iostream>
#include<cstring>
#include<cmath>
#include<iomanip>
using namespace std;
const int inf=1e7+10;
const int maxn=300;
int x[maxn],y[maxn],n;
double map[maxn][maxn];
double dis[maxn],mark[maxn];
void dijkstra(int s)
{
    
    
    memset(mark,0,sizeof(mark));//标记初始化
    for(int i=1;i<=n;i++)
        dis[i]=inf;//默认无穷距离
    dis[s]=0;//起点
    for(int i=1;i<=n;i++)
    {
    
    
        int k,minimum=inf;
        for(int j=1;j<=n;j++)
        {
    
    
            if(mark[j]==0 && dis[j]<minimum)
            {
    
    
                k=j;//记录dis[]最短路的下标
                minimum=dis[j];//记录最短距离
            }
        }
        mark[k]=1;//走过
        for(int j=1;j<=n;j++)
            dis[j]=min(dis[j],max(dis[k],map[k][j]));//dis[j]为从1号石头到第j号石头所有通路中最长边中的最小边,也就是题目所说的minimax
    }//minimax可以理解为花最短的时间去最远的地方
}
int main()
{
    
    
    int times=1;
    while(cin>>n && n)
    {
    
    
        memset(map,0,sizeof(map));
        for(int i=1;i<=n;i++)
            cin>>x[i]>>y[i];
        for(int i=1;i<=n;i++)
            for(int j=i+1;j<=n;j++)
                map[i][j]=map[j][i]=sqrt(double(x[i]-x[j])*(x[i]-x[j])+double(y[i]-y[j])*(y[i]-y[j]));//坐标之间的距离
        dijkstra(1);//Freddy的石头,也就是起点
        cout<<"Scenario #"<<times++<<endl;
        cout<<fixed<<setprecision(3)<<"Frog Distance = "<<dis[2]<<endl;//第2块是Fiona的石头,也就是终点,小数点输出后三位
        cout<<endl;
    }
    return 0;
}

Tres, resumen

Estas son variantes de las preguntas del algoritmo de plantilla de Dijkstra. Se agregan algunas condiciones o se imponen algunas restricciones. Debe comprender el significado de la pregunta y analizarla en el proceso de resolución del problema. Después de resolver el problema, cambie la plantilla para lograr los requisitos del problema. Puede ver aquí. Contraste con un blog escrito por Konjac antes: Plantilla estilo tonto: plantilla de código general de Dijkstra

Supongo que te gusta

Origin blog.csdn.net/jotaro07/article/details/110939963
Recomendado
Clasificación