贪心算法(算法分析与设计)

来源:互联网 发布:诲汝知之乎的意思 编辑:程序博客网 时间:2024/05/18 01:51

1.活动安排问题

使剩余安排时间极大化

#include<iostream>#include<algorithm>#include<vector>using namespace std;struct Node{int s;int f;};bool cmp(Node a,Node b){return a.f<b.f;}int greedySelector(vector<Node> &x,vector<bool> &a){int n=x.size()-1;int j=0;int count=1;a[0]=true;for(int i=1;i<=n;i++){if(x[i].s>=x[j].f){a[i]=true;j=i;count++;}else{a[i]=false;}} return count;}int main(){vector<Node> n;vector<bool> a;int num;cin>>num;for(int i=0;i<num;i++){Node temp;cin>>temp.s>>temp.f;n.push_back(temp);a.push_back(false);}sort(n.begin(),n.end(),cmp);cout<<greedySelector(n,a)<<endl;return 0;}

2.最优装载

#include<iostream>#include<vector>#include<algorithm>#include<cstdlib>using namespace std;struct Node{double w;int i;};bool cmp(Node a,Node b){return a.w<b.w;}double random(int start,int end){return (start+rand()%(end-start)+0.0)/10;}int loading(vector<Node> &x,vector<int> &a,double c){int i=0;while(i<x.size()){if(x[i].w<=c){c=c-x[i].w;a.push_back(x[i].i);i++;}else{break;}}return i;}int main(){vector<Node> n;vector<int> a;int num;double c;cin>>num>>c;for(int i=0;i<num;i++){Node temp;temp.w=random(1,2000);temp.i=i;n.push_back(temp);cout<<"n["<<i<<"]: "<<temp.w<<"\t";}cout<<endl;sort(n.begin(),n.end(),cmp);cout<<loading(n,a,c)<<endl;return 0;} 

3.哈夫曼编码

#include<iostream>#include<cstdlib>#include<queue>using namespace std;struct Tree{Tree* lchlid;Tree* rchlid;int f;//频率int data;//值 };struct cmp//与sort的cmp不同,结构体中重载调用操作符。也可以重载>操作符,priority_queue<Node,vector<Node>,greater<Node>> Q;{ bool operator()(Tree a,Tree b) { return a.f>b.f;//>升序,<降序  }};int random(int start,int end){return start+rand()%(end-start);}void HuffmanTree(priority_queue<Tree,vector<Tree>,cmp> &q) {while(q.size()>=2){/*Tree a=q.top();cout<<"&a="<<&a<<endl;//局部变量的地址每次申请的都是相同的,所以后续错了q.pop();Tree b=q.top();cout<<"&b="<<&b<<endl;/花了2个多小时查的,此处需注意了q.pop();Tree c;c.lchlid=&a;c.rchlid=&b;c.f=a.f+b.f;c.data=-1;q.push(c);*/Tree *a=new Tree;a->data=q.top().data;a->lchlid=q.top().lchlid;a->rchlid=q.top().rchlid;a->f=q.top().f;q.pop();Tree *b=new Tree;b->data=q.top().data;b->lchlid=q.top().lchlid;b->rchlid=q.top().rchlid;b->f=q.top().f;q.pop();Tree c;c.lchlid=a;c.rchlid=b;c.f=a->f+b->f;c.data=-1;q.push(c);}}void LT(const priority_queue<Tree,vector<Tree>,cmp> &p){queue<Tree*> q;Tree n=p.top();q.push(&n);while(!q.empty()){Tree *temp=q.front();q.pop();    if(temp->data==-1){cout<<"Node\t";}else{cout<<temp->f<<"\t";}if(temp->lchlid!=NULL){q.push(temp->lchlid);}if(temp->rchlid!=NULL){q.push(temp->rchlid);}}}int main(){int num;priority_queue<Tree,vector<Tree>,cmp> q;cin>>num;for(int i=0;i<num;i++){Tree temp;temp.lchlid=NULL;temp.rchlid=NULL;temp.f=random(0,1000);temp.data=random(1,50);q.push(temp);cout<<temp.f<<"\t";}cout<<endl;HuffmanTree(q); LT(q);}

4.单源最短路径

此处直接使用了书本测试数据,代码写死了。可以用vector来代替重写

#include<iostream>#include<vector>#include<climits>using namespace std;int getMin(int dist[5],bool vt[5]){int min=INT_MAX;int mark;for(int i=0;i<5;i++){if(!vt[i]&&min>dist[i]&&dist[i]>0){min=dist[i];mark=i;}}return mark;}void dijkstra(int dis[5][5],bool vt[5],int dist[5],int v){int mark;vt[v]=true;for(int i=0;i<5;i++){dist[i]=dis[v][i];cout<<dist[i]<<"\t";}cout<<endl;for(int j=1;j<5;j++){mark=getMin(dist,vt);vt[mark]=true;for(int i=0;i<5;i++){if(!vt[i]&&((dist[i]>0&&dist[mark]+dis[mark][i]<dist[i]&&dis[mark][i]>0)||(dist[i]<0&&dis[mark][i]>0&&dis[mark][i]>0))){dist[i]=dist[mark]+dis[mark][i];}cout<<dist[i]<<"\t";}cout<<endl;}}int main(){int dis[5][5]={{0,10,-1,30,100},{-1,0,50,-1,-1},{-1,-1,0,-1,10},{-1,-1,20,0,60},{-1,-1,-1,-1,0}};bool vt[5]={false};int dist[5]={-1};int v;cin>>v;dijkstra(dis,vt,dist,v);cout<<"the distance is:"<<endl;for(int i=0;i<5;i++){cout<<dist[i]<<"\t";}}
5.最小生成树

直接用了年前敲过的代码

A.Prim最小生成树

/************************************************************************************************************************** Prim最小生成树:1.从顶点0开始搜素最小权边                2.搜索到最短边之后,将另一个顶点u加入点集,将最短边值加入ret(总边权值)3.判断从顶点u出发的边map[u][j](j为未加入点集的点),是否小于原先点集的点到点j的距离,如果是就替换掉4.prim是遍历顶点,所以邻接矩阵比较合适***************************************************************************************************************************/ #define MaxN 101int n,ret;int map[MaxN][MaxN];void prim(){int closet[MaxN];//该点是否加入点集,1表示加入,0表示不加入 int dist[MaxN];//待搜索边集,从某个顶点出发的所有带权值边 int i,j;for(i=0;i<n;i++){closet[i]=0;//初始化全未加入dist[i]=map[0][i];//初始化待搜索边集为顶点0的边集 }closet[0]=1;//顶点0,加入点集int u,min;for(i=1;i<n;i++)//共n-1条边需要加入边集(直到所有点加入点集){min=100001;for(j=1;j<n;j++)//搜索待选边集最小边权边{if(!closet[j]&&dist[j]<min&&dist[j]>0)//点j未加入点集,点j与顶点之间的有边,且边权小于min{u=j;min=dist[j];}}closet[u]=1;//顶点u加入点集ret=ret+min;//总边权值for(j=1;j<n;j++){if(!closet[j]&&map[u][j]<dist[j])//从点u出发到点j的边小于点集其他点到点j的边&&点j未加入点集,则更新边权{ dist[j]=map[u][j];//将待搜索边集改为顶点u的边集}} } }
B.Kruscal最小生成树
#include<iostream>#include<queue>using namespace std;#define Maxv 100+5struct Node{int v2;int v1;int len;};struct cmp{bool operator()(Node a,Node b){return a.len>b.len;}};int dis[Maxv][Maxv];//dis[i][j]等于0时表示不连通 ,不等于1时表示边权值 int fa[Maxv];//father,并查集 int Getfa(int i)//查找根节点的函数 {if(fa[i]!=i)//如果不是根节点 fa[i]=Getfa(fa[i]);//找根节点 return fa[i];//返回节点i所在集合的根节点} int main(){    int sum;//最小生成树代价     priority_queue<Node,vector<Node>,cmp> Q;//声明小顶堆,返回最小数    int vn;//图中的顶点个数  int i; int j;    cin>>vn;//输入图 for(i=1;i<=vn;i++) {for(j=1;j<=vn;j++){cin>>dis[i][j];   } }  for(i=1;i<=vn;i++) {fa[i]=i;//并查集,father,一开始有vn个节点,就有vn个集合  } while(!Q.empty()) {Q.pop(); } //把每条边压入堆中 for(i=1;i<vn;i++)  { for(j=i+1;j<=vn;j++) {if(dis[i][j])//如果边权值不为0,即顶点之间有边,压入该边 {Node e; e.v1=i;  e.v2=j;  e.len=dis[i][j];  Q.push(e);  }  }    }    sum=0;    while(Q.size()!=0)    {  Node e;   e=Q.top();   Q.pop();   if(Getfa(e.v1)!=Getfa(e.v2))//若两个顶点不属于同一个点集,表示该边不是回路;也即两个节点的根节点是否相同    {                           //根节点不同,则为不同集合,不构成回路      sum=sum+e.len;    fa[Getfa(e.v2)]=Getfa(e.v1);//把e.v1的根节点作为e.v2的根节点的爹,也即合并两个集合      }    }    cout<<sum;  return 0;    }

6.贪心算法的理论基础







0 0