Diseño y análisis de algoritmos --- algoritmo codicioso

Diseño y análisis de algoritmos: algoritmo codicioso (actualización continua ...)

El concepto de algoritmo codicioso:
Independientemente de la solución óptima general, cada paso es encontrar primero la solución óptima actual, solo me importa la óptima actual, el primer paso es el mejor, el segundo paso es el mejor y el conjunto es también lo mejor al final.! Por supuesto, este algoritmo también tiene sus limitaciones: para algunos problemas, cada paso es óptimo y puede que no sea óptimo en su conjunto.

Un ejemplo que no se puede resolver con codicia :
Inserte la descripción de la imagen aquí
los pasos de la solución:
Inserte la descripción de la imagen aquí

Pregunta uno, organización del evento:

Descripción del problema:
Cada una de las n actividades tiene una hora de inicio sy una hora de finalización f. Cuando una actividad está en progreso, no se pueden realizar otras actividades durante este período de tiempo [s, f). Resuelva la disposición óptima del plan de actividades para hacer uso del tiempo La tasa más alta, es decir, el tiempo total de programación de actividades / (max_f-min_s);
entrada:
entrada n es el número de actividades, y cada una de las siguientes n líneas ingresa
la hora de inicio de la actividad y la tiempo de finalización de la actividad Se
utiliza el plan de arreglo óptimo
Salida de maximización de tiempo :
salida el
tiempo ocupado por el plan de arreglo óptimo / tiempo total
y el plan de arreglo de actividad (salida n 0 o 1, 1 significa arreglo, 0 significa sin arreglo);
input_case:

11
1 4
3 5
0 6
5 7
3 8
5 9
6 10
8 11
8 12
2 13
12 14

output_case:

10/14
1 0 0 1 0 0 0 1 0 0 1

Idea:
Primero organice de acuerdo con f de pequeña a grande, primero organice la actividad con la f más pequeña, calcule ahora = f, luego encuentre s_i> = ahora, si s_i> = ahora,
organice la actividad y asigne ahora a i, encuentre el último problema a su vez y resolverlo;
código:

#include<stdio.h>
#include<algorithm>

using namespace std;
 
typedef struct Node{
    
    
	int s;
	int f;
	int isok;
}Act;

bool cmp(Act a,Act b){
    
    
	return a.f<b.f;
}

void f(Act *a,int n){
    
    
	a[0].isok=1;
	int j=0;
	
	for(int i=1;i<n;i++){
    
    
		if(a[i].s>=a[j].f){
    
    
			a[i].isok=1;
			j=i;
		}else{
    
    
			a[i].isok=0;
		}
	}
	return ;
}

int main(){
    
    
	int n;
	scanf("%d",&n);
	Act a[n];
	for(int i=0;i<n;i++){
    
    
		scanf("%d %d",&a[i].s,&a[i].f);
		a[i].isok=0;
	}
	
	sort(a,a+n,cmp);//需要对结构体数组排序,按f从小到大的顺序排序
	f(a,n);
	int sum=0;
	int min_s=a[0].s;
	int max_f=a[0].f;
	for(int i=0;i<n;i++){
    
    
		if(a[i].isok==1){
    
    
			sum+=a[i].f-a[i].s;
		}
		if(a[i].s<min_s){
    
    
			min_s=a[i].s;
		}
		if(max_f<a[i].f){
    
    
			max_f=a[i].f;
		}
	}
	
	printf("%d/%d\n",sum,max_f-min_s);
	for(int i=0;i<n;i++){
    
    
		printf("%d",a[i].isok);
		if(i<n-1)printf(" ");
	}
	
	return 0;
}

Problema dos, problema de carga óptima

Descripción del problema:
n contenedores se cargan en un barco con una carga de c, 1 está cargado, 0 no está cargado y cuántas cajas se pueden cargar como máximo (sin considerar el problema del espacio).
Cada caja tiene su propio peso y número;
entrada:
ingrese un número entero positivo n y un número entero positivo c, que representan respectivamente el número de cajas de carga y la carga del barco; la
siguiente línea ingresa n números enteros positivos para representar el peso de n contenedores ;
Salida: muestra
el grado de carga óptimo:
el número de cargadas / el número total de cajas
muestra el estado de carga de cada caja:
(según el número de caja 1-n, genera una cadena de 0 o 1, separada por espacios, 1 está cargado, 0 no es Load)
input_case:

5 6
1 4 3 2 6

output_case:

最大装载度:
3/5
编号1-n的装载情况:
1 0 1 1 0

Idea:
Ordene según el peso de pequeño a grande, y cárguelos en orden hasta que ya no puedan instalarse, es decir, se puede maximizar la cantidad según el principio de mechero primero.
código:

#include<stdio.h>
#include<algorithm>

using namespace std;

typedef struct elem{
    
    
	int x;     //编号 
	int weight;//重量 
	int isok;  //是否被装入,0为不装入,1为转入; 
}elem;

bool cmp_weight(elem e1,elem e2){
    
    
	return e1.weight<e2.weight;
}

bool cmp_x(elem e1,elem e2){
    
    
	return e1.x<e2.x;
}

int main(){
    
    
	int n,c;
	scanf("%d %d",&n,&c);
	elem a[n];	
	for(int i=0;i<n;i++){
    
    
		scanf("%d",&a[i].weight);
		a[i].isok=0;
		a[i].x=i+1;
	}
	sort(a,a+n,cmp_weight);//按重量从小到大排好
	
	int sum=0;
	int i;
	for(i=0;i<n&&sum<=c;i++){
    
    
		sum+=a[i].weight;//轻者优先
		a[i].isok=1;
	}
	if(sum>c){
    
    //退一步,以满足题意
		a[i-1].isok=0;
		sum-=a[i-1].weight;
	}
	int sum_isok=0;
	for(int i=0;i<n;i++){
    
    
		if(a[i].isok==1){
    
    
			sum_isok++;
		}
	}
	
	sort(a,a+n,cmp_x);//最后再按编号从小到大排好
	printf("最大装载度:\n%d/%d\n",sum_isok,n);
	printf("编号1-n的装载情况:\n");
	for(int i=0;i<n;i++){
    
    
		printf("%d",a[i].isok);
		if(i<n-1)printf(" ");
	}
	return 0;
}

Problema tres, problema de la ruta más corta de una sola fuente (algoritmo dijkstra)

Descripción del problema:
Para el gráfico dirigido ponderado G (V, E), encuentre la longitud de trayectoria más corta desde el punto a al punto b, y dé salida a -1 si no puede ir;

entrada:
ingrese cuatro enteros positivos:
nm aa bb
representa el número de nodos, el número de bordes, el punto de inicio y el punto final; las
siguientes m líneas ingresan cada línea de entrada: ii jj len
es la distancia desde el nodo ii hasta node jj len;
salida:
Si no hay forma de ir de aa a bb, salida: ¡de ninguna manera! \ nSi
hay la ruta más corta, muestra la longitud de la ruta más corta: minlen way:% d \ n
input_case:

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

output_case:

minlen way:7

código:

#include<stdio.h>
#define   SIZE   99
#define   INF    9999999
int M[SIZE][SIZE];

int main(){
    
    
	
	int n,m;
	int aa,bb;
	scanf("%d %d",&n,&m);
	scanf("%d %d",&aa,&bb);
	
	for(int i=1;i<=n;i++){
    
    
		for(int j=1;j<=n;j++){
    
    
			M[i][j]=INF;
		}
	}
	
	int ii,jj,len;
	for(int i=0;i<m;i++){
    
    
		scanf("%d %d %d",&ii,&jj,&len);
		M[ii][jj]=len;
	}
	
	int sum=0;
	int isput[n+1]={
    
    0};
	int prim[n+1]={
    
    0};
	for(int i=1;i<=n;i++){
    
    
		prim[i]=M[aa][i];
	}
	
	prim[aa]=0;
	isput[aa]=1;
	prim[0]=INF;
	int flag=0;
	
	while(1){
    
    
		int j=0;
		for(int i=1;i<=n;i++){
    
    
			if(prim[i]<prim[j]&&isput[i]==0){
    
    
				j=i;
			}
		}
		
		if(j==0){
    
    
			flag=0;
			break;
		}
		isput[j]=1;
		if(j==bb){
    
    
			flag=1;
			break;
		}
		
		for(int i=1;i<=n;i++){
    
    
			if(isput[i]==0&&M[j][i]+prim[j]<prim[i]){
    
    
				prim[i]=M[j][i]+prim[j];
			}
		}
	}
	
	if(flag==0){
    
    
		printf("no way!\n");
	}else{
    
    
		printf("minlen way:%d\n",prim[bb]);
	}
	
	return 0;
}

Problema cuatro, problema de árbol de expansión mínimo (algoritmo prim)

Se presenta el problema:
hay n nodos, cómo construir una carretera, hacer que cada nodo esté conectado (formar un gráfico conectado) y minimizar el costo de la carretera;
aquí para simplificar el problema, ¡solo discuta el gráfico no dirigido!
entrada:
ingrese un entero positivo n, m
representan respectivamente el número de nodos y el número de carreteras.
Las entradas aa, bb y len en cada fila de las siguientes m líneas
son el punto de partida, el punto final y la longitud de la carretera respectivamente;
salida:
salida el costo mínimo de construcción de una carretera (ver Ejemplo) ¡
Si la salida no se puede conectar de ninguna manera!
input_case:

6 15
1 2 5
1 3 3
1 4 7
1 5 4
1 6 2
2 3 4
2 4 6
2 5 2
2 6 6
3 4 6
3 5 1
3 6 1
4 5 10
4 6 8
5 6 3

output_case:

min pay:12

código:

//prim算法 
#include<stdio.h>

#define   INF    99999
#define   SIZE   99

int M[SIZE][SIZE];

int main(){
    
    
	
	int n,m;
	scanf("%d %d",&n,&m);
	for(int i=1;i<=n;i++){
    
    
		for(int j=1;j<=n;j++){
    
    
			M[i][j]=INF;
		}
	}
	
	int aa,bb,len;
	
	for(int i=0;i<m;i++){
    
    
		scanf("%d %d %d",&aa,&bb,&len);
		M[aa][bb]=len;
		M[bb][aa]=len;
	}
	
	int dist[n+1]={
    
    0};
	int put[n+1]={
    
    0};
	for(int i=1;i<=n;i++){
    
    
		dist[i]=M[1][i];
	}
	dist[1]=0;
	put[1]=1;
	dist[0]=INF;
	int sum=0;
	while(1){
    
    
		int j=0;
		for(int i=1;i<=n;i++){
    
    
			if(dist[i]<dist[j]&&put[i]==0){
    
    
				j=i;
			}
		}
		
		if(j==0)break;
		
		sum+=dist[j];
		put[j]=1;
		
		for(int i=1;i<=n;i++){
    
    
			if(dist[i]>M[i][j]){
    
    
				dist[i]=M[i][j];
			}
		}
	}
	int flag=0;
	for(int i=1;i<=n;i++){
    
    
		if(put[i]==0){
    
    
			flag=1;
			break;
		}
	}
	if(flag==1){
    
    
		printf("no way!\n");
	}else{
    
    
		printf("min pay:%d\n",sum);
	}
	return 0;
} 

Supongo que te gusta

Origin blog.csdn.net/timelessx_x/article/details/115053106
Recomendado
Clasificación