Algorithm design and analysis---greedy algorithm

Algorithm design and analysis—greedy algorithm (continuous update...)

The concept of greedy algorithm:
Regardless of the overall optimal solution, each step is to find the current optimal solution first, I only care about the current optimal, the first step is optimal, the second step is optimal, and the whole is also optimal in the end. ! Of course, this algorithm also has its limitations. For some problems, each step is optimal and may not be optimal as a whole.

An example that cannot be solved with greed :
Insert picture description here
the steps of the solution:
Insert picture description here

Question one, event arrangement:

Problem description:
Each of n activities has a start time s and an end time f. When an activity is in progress, other activities cannot be carried out during this period of time [s, f). Solve the optimal arrangement of the activity plan to make time use The highest rate, that is, the total time of scheduling activities/(max_f-min_s);
input:
input n is the number of activities, and each of the next n lines enters
the start time of the activity and the end time of the activity. The
optimal arrangement plan is used Time maximization
output:
output the
time/total time occupied by the optimal arrangement plan
and the activity arrangement plan (output n 0 or 1, 1 means arrangement, 0 means no arrangement);
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:
First arrange according to f from small to large, first arrange the activity with the smallest f, calculate now=f, then find s_i>=now, if s_i>=now,
arrange the activity, and assign now to i, find the last problem in turn and solve it;
code:

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

Problem two, optimal loading problem

Problem description:
n containers are loaded on a ship with a load of c, 1 is loaded, 0 is not loaded, and how many boxes can be loaded at most (without considering the space issue).
Each box has its own weight and number;
input:
input a positive integer n and a positive integer c, respectively representing the number of loading boxes and the load of the ship; the
next line enters n positive integers to represent the weight of n containers ;
Ouput:
output the optimal loading degree:
the number of loaded / the total number of boxes
output the loading status of each box:
(according to the box number 1-n, output a string of 0 or 1, separated by spaces, 1 is loaded, 0 is not Load)
input_case:

5 6
1 4 3 2 6

output_case:

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

Idea:
Arrange according to weight from small to large, and load them in order until they can no longer be installed. That is to say, according to the principle of lighter first, the quantity can be maximized.
code:

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

Problem three, single source shortest path problem (dijkstra algorithm)

Problem description:
For the weighted directed graph G(V, E), find the shortest path length from point a to point b, and output -1 if it can't go;

input:
input four positive integers:
nm aa bb
respectively represent the number of nodes, the number of edges, the start point, and the end point; the
next m lines enter each line of input: ii jj len
is the distance from node ii to node jj len;
output:
If there is no way to go from aa to bb, output: no way!\nIf
there is the shortest path, output the length of the shortest path: 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

code:

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

Problem four, minimum spanning tree problem (prim algorithm)

The problem is introduced:
there are n nodes, how to build a road, make each node connected (form a connected graph), and minimize the cost of the road;
here to simplify the problem, only discuss the undirected graph!
input:
input a positive integer n, m
respectively represent the number of nodes and the number of roads.
The input aa, bb, and len in each row of the next m lines
are the starting point, the end point, and the length of the road respectively;
output:
output the minimum cost of building a road (see Example)
If the output cannot be connected no way!
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

code:

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

Guess you like

Origin blog.csdn.net/timelessx_x/article/details/115053106