电子说
贪心算法是指在对问题求解时,总是做出在当前看来是最好的选择。也就是说,不从整体最优上加以考虑,只做出在某种意义上的局部最优解。贪心算法不是对所有问题都能得到整体最优解,关键是贪心策略的选择,选择的贪心策略必须具备无后效性,即某个状态以前的过程不会影响以后的状态,只与当前状态有关。
贪心算法没有固定的算法框架,算法设计的关键是贪心策略的选择。必须注意的是,贪心算法不是对所有问题都能得到整体最优解,选择的贪心策略必须具备无后效性(即某个状态以后的过程不会影响以前的状态,只与当前状态有关。)
所以,对所采用的贪心策略一定要仔细分析其是否满足无后效性。
解题的一般步骤是:
1.建立数学模型来描述问题;
2.把求解的问题分成若干个子问题;
3.对每一子问题求解,得到子问题的局部最优解;
4.把子问题的局部最优解合成原来问题的一个解。
不能保证求得的最后解是最佳的
不能用来求最大值或最小值的问题
只能求满足某些约束条件的可行解的范围
贪心策略适用的前提是:局部最优策略能导致产生全局最优解。
实际上,贪心算法适用的情况很少。一般对一个问题分析是否适用于贪心算法,可以先选择该问题下的几个实际数据进行分析,就可以做出判断。
所谓贪心选择性质是指所求问题的整体最优解可以通过一系列局部最优的选择,换句话说,当考虑做何种选择的时候,我们只考虑对当前问题最佳的选择而不考虑子问题的结果。这是贪心算法可行的第一个基本要素。贪心算法以迭代的方式作出相继的贪心选择,每作一次贪心选择就将所求问题简化为规模更小的子问题。对于一个具体问题,要确定它是否具有贪心选择性质,必须证明每一步所作的贪心选择最终导致问题的整体最优解。
当一个问题的最优解包含其子问题的最优解时,称此问题具有最优子结构性质。问题的最优子结构性质是该问题可用贪心算法求解的关键特征。
从问题的某一初始解出发:
while (朝给定总目标前进一步){利用可行的决策,求出可行解的一个解元素。}
由所有解元素组合成问题的一个可行解;
如果大家比较了解动态规划,就会发现它们之间的相似之处。最优解问题大部分都可以拆分成一个个的子问题,把解空间的遍历视作对子问题树的遍历,则以某种形式对树整个的遍历一遍就可以求出最优解,大部分情况下这是不可行的。贪心算法和动态规划本质上是对子问题树的一种修剪,两种算法要求问题都具有的一个性质就是子问题最优性(组成最优解的每一个子问题的解,对于这个子问题本身肯定也是最优的)。动态规划方法代表了这一类问题的一般解法,我们自底向上构造子问题的解,对每一个子树的根,求出下面每一个叶子的值,并且以其中的最优值作为自身的值,其它的值舍弃。而贪心算法是动态规划方法的一个特例,可以证明每一个子树的根的值不取决于下面叶子的值,而只取决于当前问题的状况。换句话说,不需要知道一个节点所有子树的情况,就可以求出这个节点的值。由于贪心算法的这个特性,它对解空间树的遍历不需要自底向上,而只需要自根开始,选择最优的路,一直走到底就可以了。



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 ;}}
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;}
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<<"["<"]:"<endl; }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];}
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<<*max_element(mintime,mintime+m)<<endl;}
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 ("%d",&a[i]);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 ",sum);}}

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 "<':' <<' '<endl; num++;}}
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 ;}}




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 ",sum);}}
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 " <" is "<endl; }}





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

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;}
审核编辑:汤梓红
全部0条评论
快来发表一下你的评论吧 !