c++算法设计:贪心算法

文章目录

    • 最大活动安排问题
    • 背包问题
    • 最优装载
    • 最小生成树
    • 单源最短路径
    • 汽车加油问题

最大活动安排问题

贪心算法采用自顶向下的方法,如此问题中n个活动,我们首先安排第一个活动,并判断下一个活动哪一个的开始时间与第一个活动的结束时间匹配。所以贪心算法总是第一步就做出选择。

给个伪代码:

template
void GreedySelector(int n, Type s[], Type f[], bool A[])
{
       A[1] = true;    //安排活动1号

       int j = 1;
       for (int i = 2;i <= n;i++) {
           if (s[i] >= f[j]) {   //判断后一个活动是否与前一个活动的时间匹配
               A[i] = true;    //安排i号
               j = i;   
           } 
           else 
               A[i] = false;   //不安排i号
       }
}

源代码:

#include
using namespace std;

void GreedySelector(int s[],int f[],int n){
	int j=0;
	cout<<"安排活动1"<=f[j]){
			cout<<"安排活动"<

背包问题

这里的背包问题和01背包问题不同点在于:物品 i 可以拆分,所以背包肯定可以装满,因为不可能有背包有空间冗余而装不进的说法。
这个问题极其简单,因为物品可以拆,所以我们一开始就放价值最大的(贪心选择)。

伪代码:

template
void Knapsack(int n,Type M,Type v[],Type w[],Type x[])
{
       Sort(n,v,w);    //以单位重量的价值从高到低排序
       int i;
       for (i = 1;i <= n;i++) x[i] = 0;

       Type c = M;      //初始容量c
       for (i = 1;i <= n;i++) {
           if (w[i] > c)  break;   //放不下
           x[i] = 1;         //放入i物品
           c -= w[i];       //容量中减去i物品的重量
       }
       if (i <= n) 
           x[i] = c / w[i];   // 剩下的空间用最后i物品部分填满
}

最优装载

与背包问题类似,一艘船上需要装载最多箱子,则我们从重量最小的开始装(贪心选择)

伪代码:

template
void Loading(int x[],  Type w[], Type c, int n)
{
        int *t = new int [n+1];
        Sort(w, t, n);          //以重量从小到大排序
        for (int i = 1; i <= n; i++) x[i] = 0;    //初始化
        for (int i = 1; i <= n && w[t[i]] <= c; i++) {x[t[i]] = 1; c -= w[t[i]];}    //一箱一箱放进船
}

最小生成树

同样我们总是从结点1开始,每次寻找路径最小的分支。
这里使用Prim算法

源代码:

#include
using namespace std;
#define inf 0x3f3f3f3f 

void Prim(int c[][10],int n){
	int lowcost[10];
	int closest[10];
	bool s[10];
	s[1] = true;
	for(int i = 2;i<=n;i++){
		lowcost[i] = c[1][i];
		closest[i] = 1;
		s[i] = false;
	}
	for(int i = 1;i>n;
	cout<<"请输入所有对顶点及其权值"<>a>>b>>w;
		c[a][b]=w;
		c[b][a]=w;
	}
	Prim(c,n);
	return 0;
}

单源最短路径

我认为这与01背包问题和最小生成树有相似之处。首先我们也从第一个节点寻找路径最短的分支,不过其中除了需要判断每个节点的最短路径,还需要考虑选取此路径是否为最优。
使用Dijkstra算法

给出源代码:

#include
using namespace std;
#define INF 0x3f3f3f3f

int c[6][6]={
	           INF,INF,INF,INF,INF,INF,
	           INF,INF,10,INF,30,100,
	           INF,INF,INF,50,INF,INF,
	           INF,INF,INF,INF,INF,10,
	           INF,INF,INF,20,INF,60,
	           INF,INF,INF,INF,INF,INF
	        };      //这里表示一个有向图,其中的值为权

void Dijkstra(int n,int v){
	int dist[n+1];//记录到顶点的最短路径长度
	int prev[n+1];//记录最短路径的前后顶点
	bool s[n+1];
	
	for(int i = 1;i <= n;i++){
		dist[i] = c[v][i];
		s[i] = false;
		
		if(dist[i] == INF)  
		    prev[i] = 0;
		else 
		    prev[i] = v;
	}
	
	dist[v] = 0; 
	s[v] = true;
	
	for(int i = 1;i <= n;i++){
		int temp = INF;
		int u = v;
		
		for(int j = 1;j <= n;j++){
		    //到顶点 j 的路径可走且为最短,将最短的路径赋给dist[j]
			if((!s[j]) && (dist[j] < temp)){
			    temp = dist[j];
			    u = j;
		    }
		}
		
		s[u] = true;
		
	    for(int j = 1;j <= n;j++){
	        //如果到顶点 j 的路径可以通过上一顶点 u 的路径 加上另一条路使其更短,将这条更短的路径赋给dist[j]
		    if((!s[j]) && (c[u][j] < INF)){
			    if(dist[u] + c[u][j] < dist[j]){
				    dist[j] = dist[u] + c[u][j];
				    prev[j] = u;   //将上一个顶点 u 记录在prev[]中
			    }
		    }
	    }
	}
	
	
	for(int i = 2;i <= n;i++){
		int j = i;
		cout<<"顶点"<

汽车加油问题

一辆汽车加满油后可以行驶 n km,路途中有 k 个加油站,a[i]表示第 i 个加油站到下一个加油站的距离,其中a[0]表示出发点到第一个加油站的距离,a[k]表示最后一个加油站到终点的距离。求从起点到终点最少加油次数。
对于给定所有距离,我们总是从起点出发寻找加油点,所以运用贪心选择。

源代码:

#include
using namespace std;

void func(int a[],int n,int k){
	int result = 0,m = n;
	if(a[k]>n){
		cout<<"No Solution!"<>n>>k;
	for(int i = 0;i<=k;i++){
		cin>>a[i];
	}
	func(a,n,k);
	return 0;
}

你可能感兴趣的:(算法)