贪心法

贪心法

<*> 贪心算法并不是从整体最优上加以考虑, 而是从局部最优考虑, 每次总是做出当前看起来最好的选择,在某种意义上的局部最优选择;

<*> 最优子结构性质 :

<*>贪心选择性质:



1、  活动安排 :

问题描述 :设有n个活动集合E = {1 ,2,…,n} ,其中每个活动i都要求使用同一资源, 而在同一时间内只有一个活动能使用这一资源。每个活动i都有一个要求使用该资源的起始时间Si和一个结束时间fi , 且Si < fi 。如果选择活动i ,则它在半开区间[Si , fi]内占用资源。若区间[Si,fi)与区间不相交,则称活动i和活动j是相容的, 也就是说Si >= fj || Sj >= fi 为真时 ,活动i和活动j是相容的。

要求:要在所给的活动集中选出最大的相容子集合;

code>>
#include
#include
#include
using namespace std;


class Activity
{
public :
	int id;
	int s;//活动开始时间
	int f;//活动结束时间

public: 
	Activity()
	{
		cin >>this->s >> this->f;
	}
	friend void Arrange();
	bool operator<(Activity &A1)
	{
		if (this->f < A1.f)
		{
			return true;
		}
		else
		{
			return false;
		}
	}
	
};

//活动集E:所给活动的集合
vector E;//竟然要加class
vector A;//相容标记集合

void Arrange()
{
	sort(E.begin() + 1, E.end());//将活动按非减序列排列
	int j = 0;
	for (int i = 1; i < E.size(); i++)
	{
		if (E[i].s >= E[j].f)
		{
			A[i] = true;
			j = i;
		}
	}

	for (int i = 0; i < A.size(); i++)
	{
		if (A[i])
		{
			cout << E[i].id<<" ";
		}
	}

}


int main()
{
	int n;//活动数量
	cin >> n;
	E.push_back(Activity());
	E[0].s = 0;
	E[0].f = 0;
	for (int i = 1; i <= n; i++)
	{
		E.push_back(Activity());
		E[i].id = E[i].s;
	}
	for (int i = 0; i <= n; i++)
	{
		A.push_back(false);
	}

	Arrange();
	return 0;
}

2、 背包问题:

给定n种物品和一个背包。物品i的重量是wi ,其价值为vi,背包的容量为c , 问应该如何选择把哪一个物品装入背包中,使得装入背包中的物品的总价值最大?

0-1背包问题:不能部分装入物品,

背包问题:可选择装入部分物品


code>>
#include
#include
#include
#include
using namespace std;
class WP
{
public :
	float w;
	float p;
public :
	WP(float w, float p)
	{
		this->w = w;
		this->p = p;
	}
	bool operator<(WP wp)
	{
		if (1.0*w/p < 1.0*wp.w/wp.p)
		{
			return true;
		}
		else
		{
			return false;
		}
	}
};
class Knapsack
{
public :
	vector wp;
	int n;
	float c;
public :
	Knapsack()
	{
		cin >> this->n >> this->c;
		wp.push_back(WP(0 , 0));
		for (int i = 1; i <= n; i++)
		{
			int in1, in2;
			cin>>in1>>in2;
			wp.push_back(WP(in1, in2));
		}

	}
};

vector < float > x;
Knapsack ks;
void GreedyKP()
{
	x.push_back(0);
	sort(ks.wp.begin() + 1, ks.wp.end());
	int sum = 0;
	int i;
	for (int i = 1; i < ks.n; i++)
	{
		x.push_back(0);
	}
	for (i = 1; i <= ks.n; i++)
	{
		if (ks.wp[i].w < ks.c)
		{
			x[i] = 1;
			ks.c -= ks.wp[i].w;
		}
		else
		{
			break;
		}
	}
	if (i < ks.n + 1)
	{
		x.push_back(1.0*ks.c/ks.wp[i].w);
	}

	for (int i = 1; i < x.size(); i++)
	{
		cout << ks.wp[i].w << " : " <

3、  最优装载 :

问题描述:有一批集装箱要装上载重量为c的轮船。其中集装箱i的重量为wi , 最优装载问题要求在装载体积不受限制的情况下,将尽可能多的集装箱装上船;

 
  

code>>
#include
#include
#include
#include
using namespace std;
//最优装载问题

class Loading
{
public :
	vector w;
	float c;
	int n;

public :
	Loading()
	{
		cin >> this->n >> this->c;
		w.push_back(0);
		for (int i = 1; i <= this->n; i++)
		{
			float in1;
			cin >> in1;
			this->w.push_back(in1);
		}
	}
};
vector x;
Loading L = Loading();

void Load()
{
	sort(L.w.begin()+1, L.w.end());
	for (int i = 0; i <= L.n; i++)
	{
		x.push_back(0);
	}
	for (int i = 1; i < L.n; i++)
	{
		if (L.w[i] <= L.c)
		{
			x[i] = 1;
			L.c -= L.w[i];
		}
		else
		{
			break;
		}
	}
	for (int i = 1; i <= L.n; i++)
	{
		if (x[i] == 1)
		{
			cout.precision(4);
			cout << "weght : " << L.w[i] << endl;
		}
	}
}

int main()
{
	Load();
	return 0;
}

4、  哈弗曼编码 :

问题描述:


code>>
Huffman.cpp
#include"BinaryTree.h"
#include
#include
#include
#include
using namespace std;

typedef BinaryTree HuffmanTree;
typedef BinaryNode HuffmanNode;
class FC
{
public :
	float m_f;
	char m_c;
public :
	FC(float f = 0 , char c = ' ')
	{
		m_f = f;
		m_c = c;
	}
	bool operator==(float f)
	{
		if (m_f == f)
		{
			return true;
		}
		else
		{
			return false;
		}
	}
};
class Huffman
{
public :
	Huffman()
	{
		cin >> n;
		fc.push_back(FC());
		fc[0].m_f = 10000;
		for (int i = 1; i <= n; i++)
		{
			float in1;
			char in2;
			cin >> in1;
			cin >> in2;
			fc.push_back(FC(in1, in2));
		}
		//生成单结点树
		for (int i = 0 ; i <= n; i++)
		{
			HuffmanTree z;
			z.MakeTree(fc[i].m_f , HuffmanTree() , HuffmanTree());
			HT.push_back(z);
		}
	}
public :
	int n;//字符总数
	vector fc;//字符出现的频率表
	vector HT;
};

Huffman huff = Huffman();
vector code;

//构建哈弗曼树
HuffmanTree MakeHuffmanTree()
{
	//建优先级队列
	priority_queue> Q;
	for (int i = 0; i <= huff.n; i++)
	{
		Q.push(huff.HT[i]);
	}

	for (int i = 1; i < huff.n; i++)
	{
		HuffmanTree x, y ,z;
		x = Q.top();
		Q.pop();
		y = Q.top();
		Q.pop();
		float w = x.m_root->m_data + y.m_root->m_data;
		z.MakeTree(w , x , y);
		Q.push(z);
	}
	return Q.top();
}

//生成编码
void Huffmancode(HuffmanNode* root)
{
	if (root != NULL)
	{
		if (root->m_pleft == NULL && root->m_pright == NULL)
		{
			vector::iterator iter = find(huff.fc.begin() + 1, huff.fc.end(), root->m_data) ;
			
			cout << iter->m_c <<"的编码 : ";
			for (int i = 1; i < code.size(); i++)
			{
				cout << code[i];
			}
			cout << endl;
		}
		if (root->m_pleft != NULL)
		{
			code.push_back(0);
			Huffmancode(root->m_pleft);
		}
		if (root->m_pright != NULL)
		{
			code.push_back(1);
			Huffmancode(root->m_pright);
		}
		
	}

	code.pop_back();
}

//译码
void Interpret(vector s , HuffmanNode* root)
{
	HuffmanNode* p = root;
	for (int i = 0; i < s.size(); i++)
	{
		if (NULL == p->m_pleft && NULL == p->m_pright)
		{
			vector::iterator iter = find(huff.fc.begin() + 1, huff.fc.end(), p->m_data);
			cout << iter->m_c;
			p = root;

		}
		if (0 == s[i])
		{
			p = p->m_pleft;
		}
		if (1 == s[i])
		{
			p = p->m_pright;
		}
	}
	cout << endl;
}
int main()
{
	HuffmanTree htree;
	htree = MakeHuffmanTree();
	code.push_back(-1);
	Huffmancode(htree.m_root);
	vector scode;

	char in;
	while ((in = getchar()) != '#')
	{
		scode.push_back(in-48);
	}
	//前提Huffman树已建立
	Interpret(scode , htree.m_root);
	return 0;
}

//上面用到的二叉树头文件BinaryTree.h
#include
//定义结点类型
template
class BinaryTree;//预引用

template
class BinaryNode
{
public:
	BinaryNode() :m_pleft(NULL), m_pright(NULL) {};//无参构造函数
	BinaryNode(Type item, BinaryNode *pleft = NULL, BinaryNode *pright = NULL) :m_data(item), m_pLeft(pleft), m_pright(pright) {};//含参构造函数

	//friend
	//friend class BinaryTree;

public :
	BinaryNode *m_pleft, *m_pright;
	Type m_data;
};

//定义二叉树
template
class BinaryTree
{
public:
	BinaryTree() : m_root(NULL){	};
	void MakeTree(Type item, BinaryTree LBTree, BinaryTree RBTree )
	{
		m_root = new BinaryNode();
	
		m_root->m_data  = item;
		m_root->m_pleft = LBTree.m_root;
		m_root->m_pright = RBTree.m_root;
	}
    friend  bool operator<(BinaryTree BT1 , BinaryTree BT2)
	{
		if (BT1.m_root->m_data < BT2.m_root->m_data)
		{
			return false;
		}
		else
		{
			return true;
		}
	}
public:
	BinaryNode *m_root;
};

5、 多机调度 :


code>>
#include
#include
#include
using namespace std;
class JOB
{
public :
	JOB()
	{
		cin >> n >> m;
		jt.push_back(0);
		mt.push_back(0);
		for (int i = 1; i <= n; i++)
		{
			int in1;
			cin >> in1;
			jt.push_back(in1);
		}
		for (int i = 1; i <= m; i++)
		{
			mt.push_back(0);
		}
	};
public :
	int n, m;
	vector jt;
	vector mt;
};
struct greater
{	
	bool operator()(int x , int y) const
	{	
		return (x > y);
	}
};

JOB J;
void greedyJOB()
{
	sort(J.jt.begin() + 1, J.jt.end() , greater());
	int i;
	vector::iterator iter;
	for (i = 1; i <= J.n; i++)
	{
		if (i <= J.m)
		{
			J.mt[i] += J.jt[i];
		}
		else
		{	
			iter = min_element(J.mt.begin() + 1, J.mt.end());
			*iter += J.jt[i];
		}
	}
	iter = max_element(J.mt.begin() + 1, J.mt.end());
	cout << *iter << endl;
}

int main()
{
	greedyJOB();
	return 0;
}

6、  Kruskal算法:


code>>
#include"UnionSet.h"
#include
#include
#include
#include
using namespace std;

class Edge
{
public :
	Edge(int i = -1, int j = -1, int weight = 1000)
	{
		this->i = i;
		this->j = j;
		this->weight = weight;
	}
	friend bool operator<(Edge E1 , Edge E2)
	{
		return (E1.weight >=  E2.weight);
	}
public:
	int i, j;
	int weight;
};

class Graph
{
public :
	Graph()
	{
		cin >> vn >> en;
		edges.push_back(Edge());
		for (int i = 1; i <= en; i++)
		{
			int in1, in2, in3;
			cin >> in1 >> in2 >> in3;
			edges.push_back(Edge(in1, in2, in3));
		}
	}
public :
	vector edges;//边集
	int vn;//顶点数
	int en;//边数
};



Graph G;
vector minspt;//存储最小生成树中各边
//克鲁斯卡尔算法
void Kruskal()
{
	priority_queue> Q(G.edges.begin()+1 , G.edges.end());
	/*Q.push(Edge());
	for (int i = 1; i <= G.en; i++)
	{
		Q.push(G.edges[i]);
	}
*/
	//初始化并查集
	vector S;
	S.push_back(PNode());
	for (int i = 1; i <= G.vn; i++)
	{
		S.push_back(PNode(i, i));
	}
	UnionSet U = UnionSet(S , G.vn);
	
	//边长递增序依次考察每条边
	Edge s1;
	vector::iterator a ,b;
	for (int i = 1; i <= G.en; i++)
	{
		s1 = Q.top();
		Q.pop();
		a = U.Find(s1.i);//s1.i所在集合的头
		b = U.Find(s1.j);//s2.j所在集合的头
		if (a->data != b->data)
		{
			minspt.push_back(s1);
			U.Union(a->data, b->data);
		}
	}
}

int main()
{
	Kruskal();
	cout << "minimum_spanning_Tree : " << endl;
	for (int i = 0; i < minspt.size(); i++)
	{
		cout<<"( " << minspt[i].i <<" , " <>上面用到的并查集:
#pragma once
#include
#include
#include
using namespace std;

class PNode
{
public:
	PNode(int d = -1, int p = -1)
	{
		data = d;
		parent = p;
	};
	bool operator==(int val)
	{
		return (data == val);
	}
public:
	int data;
	int parent;//存在父子关系的就在同一个连通分支,parent是自己的结点,他就是该集合的代表;
};



class UnionSet
{
public:
	UnionSet()//初始化集合
	{
		cin >> n;
		s.push_back(PNode(0, 0));
		for (int i = 1; i <= n; i++)
		{
			int in1;
			int in2;
			cin >> in1 >> in2;
			s.push_back(PNode(in1, in2));
		}
	};
	UnionSet(vector s, int n)
	{
		this->s = s;
		this->n = n;
	};
	void Union(int s1, int s2)
	{
		//合并成员s1, s2所在的两个连通分支
		/*vector::iterator iter1, iter2;

		iter1 = Find(s1);
		iter2 = Find(s2);
		if(iter1->data != iter2->data)
		{
			iter2->parent = iter1->data;
		}*/

		//合并代表s1 , s2所在的连通分支
		vector::iterator iter1, iter2;
		iter1 = find(s.begin() + 1, s.end(), s1);
		iter2 = find(s.begin() + 1, s.end(), s2);
		iter2->parent = iter1->data;
	};
	vector::iterator Find(int m)//查找成员m所在集合的代表,返回它的位置
	{
		vector::iterator iter , p , q , r;
		iter = find(s.begin() + 1, s.end(), m);
		//路径压缩
		p = iter;
		while (p->parent != p->data)
		{
			p = find(s.begin() + 1, s.end(), p->parent);//返回代表的位置
		}

		r = iter;//指向当前
		q = find(s.begin() + 1, s.end(), r->parent);//指向上级
		while (q != p)
		{
			r->parent = p->parent;
			r = q;//上位
			q = find(s.begin() + 1, s.end(), q->parent);//上位
		}

		return p;//返回树根,即代表
	}
public :
	vector s;
	int n;
};

7、  Prim算法:

code>>感觉写复杂了。。。。。。
#include
#include
#include
using namespace std;

class EdgeNode
{
public :
	EdgeNode(int i = 0  , int j = 0 , int w = 10000)
	{
		this->i = i;
		this->j = j;
		this->weight = w;
	}
	
	friend bool operator==(EdgeNode E1 , EdgeNode E2)
	{
		return  ((E1.i == E2.i && E1.j == E2.j) || (E1.i == E2.j && E1.j == E2.i));
	
	}
	
public :
	int i, j;
	int weight;
};
class Graph
{
public :
	Graph()
	{
		cin >> vn >> en;
		edges.push_back(EdgeNode());
		for (int i = 1; i <= en; i++)
		{
			int in1, in2, in3;
			cin >> in1 >> in2 >> in3;
			edges.push_back(EdgeNode(in1, in2, in3));
		}
		minspt.push_back(EdgeNode());
	}
	EdgeNode  Find(int i, int j)
	{
		EdgeNode e = EdgeNode(i, j, 0);
		vector::iterator iter;
		iter = find(edges.begin() + 1, edges.end(), e);
		if (iter != edges.end())
		{
			return EdgeNode(i, j, iter->weight);
		}
		else
		{
			return EdgeNode(i, j, 10000);
		}
		 
	}
public :
	int vn, en;
	vector edges;
	vector minspt;
};
Graph G;
vector closest;//closest[i] : 从V-S中的顶点i到S中最近的j顶点的相应的边
vector s;//已选择的顶点标记为true;

bool comp(EdgeNode E1 ,EdgeNode E2 )//E1 类似扫描器p, E2类似min
{
	if (!s[E1.i])
	{
		return (E1.weight < E2.weight);
	}
	else
	{
		return false;
	}
}
void prim()
{
	EdgeNode e1, e2;
	vector::iterator iter;
	
	closest.push_back(EdgeNode());

	//初始化closest , s;
	for (int i = 0; i <= G.vn; i++)
	{
		s.push_back(false);
	}
	s[0] = s[1] = true;
	for (int i = 1; i <= G.vn; i++)//到1的最近边
	{
		if (!s[i])
		{
			e1 = G.Find(i, 1);
			closest.push_back(EdgeNode(i, 1, e1.weight));
		}
		else
		{
			closest.push_back(EdgeNode());
		}
	}

	for (int j = 1; j < G.vn; j++)
	{
		int k = 0;
		iter = min_element(closest.begin() + 1, closest.end(), comp);
		k = iter->i;
		if (k)
		{
			s[k] = true;//顶点k加入S中
			G.minspt.push_back(*iter);
			//修改closet
			for (int i = 1; i <= G.vn; i++)
			{
				if (!s[i])
				{
					e1 = G.Find(i, closest[i].j);
					e2 = G.Find(i, k);
					if (e1.weight > e2.weight)//i到S中的新加的顶点k更近,更新closest
					{
						closest[i] = e2;
					}
				}
			}
		}
	}
}

int main()
{
	prim();
	cout << "minimum_spanning_Tree : " << endl;
	for (int i = 1; i <= G.minspt.size()-1; i++)
	{
		cout << "( " << G.minspt[i].j << " , " << G.minspt[i].i << " , " << G.minspt[i].weight << " )" << endl;
	}
	return 0;
}



 
  

 
  

你可能感兴趣的:(算法设计与分析)