赞
踩
贪心算法是指在对问题求解时,总是做出在当前看来是最好的选择。也就是说,不从整体最优上加以考虑,只做出在某种意义上的局部最优解。贪心算法不是对所有问题都能得到整体最优解,关键是贪心策略的选择,选择的贪心策略必须具备无后效性,即某个状态以前的过程不会影响以后的状态,只与当前状态有关。
贪心算法没有固定的算法框架,算法设计的关键是贪心策略的选择。必须注意的是,贪心算法不是对所有问题都能得到整体最优解,选择的贪心策略必须具备无后效性(即某个状态以后的过程不会影响以前的状态,只与当前状态有关。)
所以,对所采用的贪心策略一定要仔细分析其是否满足无后效性。
解题的一般步骤是:
1.建立数学模型来描述问题;
2.把求解的问题分成若干个子问题;
3.对每一子问题求解,得到子问题的局部最优解;
4.把子问题的局部最优解合成原来问题的一个解。
不能保证求得的最后解是最佳的
不能用来求最大值或最小值的问题
只能求满足某些约束条件的可行解的范围
贪心策略适用的前提是:局部最优策略能导致产生全局最优解。
实际上,贪心算法适用的情况很少。一般对一个问题分析是否适用于贪心算法,可以先选择该问题下的几个实际数据进行分析,就可以做出判断。
所谓贪心选择性质是指所求问题的整体最优解可以通过一系列局部最优的选择,换句话说,当考虑做何种选择的时候,我们只考虑对当前问题最佳的选择而不考虑子问题的结果。这是贪心算法可行的第一个基本要素。贪心算法以迭代的方式作出相继的贪心选择,每作一次贪心选择就将所求问题简化为规模更小的子问题。对于一个具体问题,要确定它是否具有贪心选择性质,必须证明每一步所作的贪心选择最终导致问题的整体最优解。
当一个问题的最优解包含其子问题的最优解时,称此问题具有最优子结构性质。问题的最优子结构性质是该问题可用贪心算法求解的关键特征。
从问题的某一初始解出发:
while (朝给定总目标前进一步){利用可行的决策,求出可行解的一个解元素。}
由所有解元素组合成问题的一个可行解;
#include #include #include using namespace std; int N; struct Act { int start; int end; }act[100010]; bool cmp(Act a,Act b) { return a.end } int greedy_activity_selector() { int num=1,i=1; for(int j=2;j<=N;j++) { if(act[j].start>=act[i].end) { i=j; num++; } } return num; } int main() { int t; scanf("%d",&t); while(t--) { scanf("%d",&N); for(int i=1;i<=N;i++) { scanf("%lld %lld",&act[i].start,&act[i].end); } act[0].start=-1; act[0].end=-1; sort(act+1,act+N+1,cmp); int res=greedy_activity_selector(); cout<endl; } }
2.钱币找零问题
#include #include using namespace std; const int N=7; int Count[N]={3,0,2,1,0,3,5}; int Value[N]={1,2,5,10,20,50,100}; int solve(int money){ int num=0; for(int i=N-1;i>=0;i--) { int c=min(money/Value[i],Count[i]); money=money-c*Value[i]; num+=c; } if(money>0) num=-1; return num; } int main(){ int money; cin>>money; int res=solve(money); if(res!=-1) cout<endl; else cout<<"NO"<<endl; }
#include using namespace std; const int N=4; void knapsack(float M,float v[],float w[],float x[]); int main() { float M=50; //背包所能容纳的重量 float w[]={0,10,30,20,5}; //每种物品的重量 float v[]={0,200,400,100,10}; //每种物品的价值 float x[N+1]={0}; //记录结果的数组 knapsack(M,v,w,x); cout<<"选择装下的物品比例:"<<endl; for(int i=1;i<=N;i++) cout<<"["<"]:"< } void knapsack(float M,float v[],float w[],float x[]) { int i; //物品整件被装下 for(i=1;i<=N;i++) { if(w[i]>M) break; x[i]=1; M-=w[i]; } //物品部分被装下 if(i<=N) x[i]=M/w[i]; }
#include #include using namespace std; int speed[10010]; int mintime[110]; bool cmp( const int &x,const int &y) { return x>y; } int main() { int n,m; memset(speed,0,sizeof(speed)); memset(mintime,0,sizeof(mintime)); cin>>n>>m; for(int i=0;icin>>speed[i]; sort(speed,speed+n,cmp); for(int i=0;i { *min_element(mintime,mintime+m)+=speed[i]; } cout<endl; }
#include #include using namespace std; int main(){ int a[1000],t,n,sum; scanf("%d",&t); while(t--) { scanf("%d",&n); sum=0; for(int i=0;iscanf( while(n>3) { sum=min(sum+a[1]+a[0]+a[n-1]+a[1],sum+a[n-1]+a[0]+a[n-2]+a[0]); n-=2; } if(n==3) sum+=a[0]+a[1]+a[2]; else if(n==2) sum+=a[1]; else sum+=a[0]; printf("%d\n",sum); } }
#include #include #include using namespace std; struct Point { double x; double y; }point[1000]; int cmp(const void *a, const void *b){ return (*(Point *)a).x>(*(Point *)b).x?1:-1; } int main(){ int n,d; int num=1; while(cin>>n>>d) { int counting=1; if(n==0&&d==0) break; for(int i=0;i { int x,y; cin>>x>>y; if(y>d) { counting=-1; } double t=sqrt(d*d-y*y); //转化为最少区间的问题 point[i].x=x-t; //区间左端点 point[i].y=x+t; //区间右端点 } if(counting!=-1) { qsort(point,n,sizeof(point[0]),cmp); //按区间左端点排序 double s=point[0].y; //区间右端点 for(int i=1;i { if(point[i].x>s) //如果两个区间没有重合,增加雷达数目并更新右端点 { counting++; s=point[i].y; } else if(point[i].y //如果第二个区间被完全包含于第一个区间,更新右端点 { s=point[i].y; } } } cout<<"Case "<':'<< num++; } }
#include #include #include #include #include #include #include using namespace std; long long int price[100010],t,n,res; int main(){ ios::sync_with_stdio(false); cin>>t; while(t--) { cin>>n; priority_queue<long long int, vector<long long int>, greater<long long int> > q; res=0; for(int i=1;i<=n;i++) { cin>>price[i]; } res-=price[1]; res+=price[n]; for(int i=2;i<=n-1;i=i+2) { long long int buy=min(price[i],price[i+1]); long long int sell=max(price[i],price[i+1]); if(!q.empty()) { if(buy>q.top()) { res=res-2*q.top()+buy+sell; q.pop(); q.push(buy); q.push(sell); } else { res=res-buy+sell; q.push(sell); } } else { res=res-buy+sell; q.push(sell); } } cout<endl; } }
#include #include #include using namespace std; int main(){ long long int sum; int i,n,t,a,b; while(~scanf("%d",&n)) { priority_queue<int,vector<int>,greater<int> >q; for(i=0;i { scanf("%d",&t); q.push(t); } sum=0; if(q.size()==1) { a=q.top(); sum+=a; q.pop(); } while(q.size()>1) { a=q.top(); q.pop(); b=q.top(); q.pop(); t=a+b; sum+=t; q.push(t); } printf("%lld\n",sum); } }
#include #include #define INF 1000 #define MAX_V 100 using namespace std; int main(){ int V,E; int i,j,m,n; int cost[MAX_V][MAX_V]; int d[MAX_V]; bool used[MAX_V]; cin>>V>>E; fill(d,d+V+1,INF); fill(used,used+V,false); for(i=0;i { for(j=0;j { if(i==j) cost[i][j]=0; else cost[i][j]=INF; } } for(m=0;m { cin>>i>>j>>cost[i][j]; cost[j][i]=cost[i][j]; } cin>>n; d[n]=0; //源点 while(true) { int v=V; for(m=0;m { if((!used[m])&&(d[m] } if(v==V) break; used[v]=true; for(m=0;m { d[m]=min(d[m],d[v]+cost[v][m]); } } for(i=0;i { cout<<"the shortest distance between "<" and "< } }
#include #include #define MAX_V 100 #define INF 1000 using namespace std; int main(){ int V,E; int i,j,m,n; int cost[MAX_V][MAX_V]; int mincost[MAX_V]; bool used[MAX_V]; cin>>V>>E; fill(mincost,mincost+V+1,INF); fill(used,used+V,false); for(i=0;i { for(j=0;j { if(i==j) cost[i][j]=0; else cost[i][j]=INF; } } for(m=0;m { cin>>i>>j>>cost[i][j]; cost[j][i]=cost[i][j]; } mincost[0]=0; int res=0; while(true) { int v=V; for(m=0;m { if((!used[m])&&(mincost[m] v=m; } if(v==V) break; used[v]=true; res+=mincost[v]; for(m=0;m { mincost[m]=min(mincost[m],cost[v][m]); } } cout<endl; }
#include #include #define MAX_E 100 using namespace std; struct edge { int u,v,cost; }; int pre[MAX_E]; edge es[MAX_E]; int find(int x); void initvalue(int x); bool same(int x,int y); void unite(int x,int y); bool comp(const edge& e1,const edge& e2); int main(){ int V,E; int i,j,m,n; cin>>V>>E; initvalue(V); for(i=0;icin>>es[i].u>>es[i].v>>es[i].cost; sort(es,es+E,comp); int res=0; for(i=0;i { edge e=es[i]; if(!same(e.u,e.v)) { unite(e.u,e.v); res+=e.cost; } } cout<endl; } bool comp(const edge& e1,const edge& e2){ return e1.cost } void initvalue(int x){ for(int i=0;i } int find(int x){ int r=x; while(pre[r]!=r) r=pre[r]; int i=x,j; while(pre[i]!=r) { j=pre[i]; pre[i]=r; i=j; } return r; } bool same(int x,int y){ if(find(x)==find(y)) return true; else return false; } void unite(int x,int y){ int fx=find(x); int fy=find(y); if(fx!=fy) pre[fx]=fy; }
-END-
来源:付斌整理
推荐阅读
【1】安谋中国“星辰”处理器商用:灵动微、全志科技、华大北斗布局合作
【2】Soitec:今明两年,FD-SOI应用或迎来腾飞拐点
【3】终于整理齐了,电子工程师“设计锦囊”,你值得拥有!
【4】半导体行业的人都在关注这几个公众号
你和大牛工程师之间到底差了啥? 加入技术交流群,与高手面对面 添加管理员微信 加入“中国电子网微信群”交流Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。