日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

第六章 贪心 【完结】

發布時間:2025/3/20 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 第六章 贪心 【完结】 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

貪心類題型沒有固定的模板只有多做題,總結經驗。
基本都熟練了

目錄

  • 905. 區間選點
  • 908. 最大不相交區間數量
  • 906. 區間分組 【有意思】
  • 907. 區間覆蓋【有意思】
  • 148. 合并果子
  • 913. 排隊打水
  • 104. 貨倉選址
  • 125. 耍雜技的牛

905. 區間選點


https://www.acwing.com/problem/content/description/907/

本題和區間合并那種題幾乎一樣的思路,不過還是有差別的。
首先:按左端點從小到達排,這是沒有懸念的必須做的。
這時候分析,會有如下幾種情況:
情況一:

這種包含的情況,我們要選小的,因為我們要的是公共部分。
情況二:

這種相交的情況選,相交的。
情況三:

不相交的情況選b,個數加1。

#include<cstdio> #include<iostream> #include<algorithm> using namespace std; const int N=1e5+10; struct student {int x,y; }stu[N]; bool cmp(student a,student b) {return a.x<b.x; } int main(void) {int n; cin>>n;for(int i=0;i<n;i++) cin>>stu[i].x>>stu[i].y;sort(stu,stu+n,cmp);int ans=1;int startx=stu[0].x,endx=stu[0].y;for(int i=1;i<n;i++){if(stu[i].x<=endx&&stu[i].y<=endx) startx=stu[i].x,endx=stu[i].y;else if(stu[i].x<=endx&&stu[i].y>endx) startx=stu[i].x;else ans++,startx=stu[i].x,endx=stu[i].y;}cout<<ans<<endl;return 0; } #include<bits/stdc++.h> using namespace std; typedef pair<int,int> PII; vector<PII> ve; int main(void) {int n; cin>>n;while(n--){int l,r; cin>>l>>r;ve.push_back({l,r});}sort(ve.begin(),ve.end());int ans=0;int l=-1e9-10,r=-1e9-5;for(int i=0;i<ve.size();i++){if(ve[i].first>r) l=ve[i].first,r=ve[i].second,ans++;else if(ve[i].second<=r) l=ve[i].first,r=ve[i].second;else if(ve[i].first<=r&&ve[i].second>=r) l=ve[i].first;}cout<<ans<<endl;return 0; }

方法二 從小到大排序右端點:

因為我們選右端點,才可能盡量大的覆蓋掉后面的區間

#include<cstdio> #include<algorithm> #include<iostream> using namespace std; const int N=1e5+10; struct node {int x,y; }Node[N]; bool cmp(node a,node b) {return a.y<b.y; } int main(void) {int n; cin>>n;for(int i=0;i<n;i++) cin>>Node[i].x>>Node[i].y;sort(Node,Node+n,cmp);int ans=0;int flag=-1e9;for(int i=0;i<n;i++){if(flag<Node[i].x) ans++,flag=Node[i].y;}cout<<ans<<endl;return 0; } #include<bits/stdc++.h> using namespace std; typedef pair<int,int> PII; vector<PII> ve; int main(void) {int n; cin>>n;while(n--){int l,r; cin>>l>>r;ve.push_back({r,l});}int flag=-1e9;int ans=0;sort(ve.begin(),ve.end());for(int i=0;i<ve.size();i++) if(flag<ve[i].second) ans++,flag=ve[i].first;cout<<ans<<endl;return 0; }

908. 最大不相交區間數量


https://www.acwing.com/problem/content/910/

老規矩:左端點從小到大排序
第一種情況:

這種得選a,這樣右邊的區間的選擇范圍才會更大。
第二種情況:

此時不用變,還是a這樣才會有更大的空間。
第三種情況:

選b,數量加1

#include<iostream> #include<cstdio> #include<algorithm> using namespace std; const int N=1e5+10; struct student {int x,y; }stu[N]; bool cmp(student a,student b) {return a.x<b.x; } int main(void) {int n; cin>>n;for(int i=0;i<n;i++) cin>>stu[i].x>>stu[i].y;sort(stu,stu+n,cmp);int ans=1;int startx=stu[0].x,endx=stu[0].y;for(int i=1;i<n;i++){if(stu[i].y<endx) startx=stu[i].x,endx=stu[i].y;else if(stu[i].x>endx) ans++,startx=stu[i].x,endx=stu[i].y;}cout<<ans<<endl;return 0; }

方法二:從小到大排序右端點

#include<cstdio> #include<iostream> #include<algorithm> using namespace std; const int N=1e5+10; struct node {int x,y; }Node[N]; bool cmp(node a,node b) {return a.y<b.y; } int main(void) {int n; cin>>n;for(int i=0;i<n;i++) cin>>Node[i].x>>Node[i].y;sort(Node,Node+n,cmp);int ans=0;int flag=-1e9;for(int i=0;i<n;i++){if(Node[i].x>flag) ans++,flag=Node[i].y;}cout<<ans<<endl;return 0; } #include<bits/stdc++.h> using namespace std; vector< pair<int,int> > ve; int main(void) {int n; cin>>n;while(n--){int l,r; cin>>l>>r;ve.push_back({r,l});}sort(ve.begin(),ve.end());int ans=0;int flag=-1e9-5;for(int i=0;i<ve.size();i++) if(ve[i].second>flag) ans++,flag=ve[i].first;cout<<ans<<endl; }

906. 區間分組 【有意思】


https://www.acwing.com/problem/content/description/908/

#include<cstdio> #include<iostream> #include<queue> #include<algorithm> using namespace std; const int N=1e5+10; struct node {int x,y; }Node[N]; bool cmp(node a,node b) {return a.x<b.x; } int main(void) {int n; cin>>n;for(int i=0;i<n;i++) cin>>Node[i].x>>Node[i].y;sort(Node,Node+n,cmp);priority_queue<int, vector<int>, greater<int> >heap;for(int i=0;i<n;i++){if(heap.empty()||heap.top()>=Node[i].x)//組為空,或者任何一個組內都放不下{heap.push(Node[i].y);}else if(heap.top()<Node[i].x)//可以放進組內{heap.pop();//將原來的區間的最右值更新heap.push(Node[i].y);}}cout<<heap.size()<<endl;return 0; } #include<bits/stdc++.h> using namespace std; vector< pair<int,int> > ve; priority_queue<int, vector<int>, greater<int> >heap; int l,r,n; int main(void) {cin>>n;while(n--) cin>>l>>r, ve.push_back({l,r});sort(ve.begin(),ve.end());for(int i=0;i<ve.size();i++){if(heap.empty()||heap.top()>=ve[i].first) heap.push(ve[i].second);else if(heap.top()<ve[i].first) heap.pop(),heap.push(ve[i].second);}cout<<heap.size()<<endl;return 0; }

907. 區間覆蓋【有意思】


https://www.acwing.com/problem/content/description/909/

對于可以覆蓋之前的,我們要選它們中最長的。

#include<cstdio> #include<iostream> #include<algorithm> using namespace std; const int N=1e5+10; struct node {int x,y; }Node[N]; bool cmp(node a,node b) {return a.x<b.x; } int main(void) {int st,ed; cin>>st>>ed;int n; cin>>n;for(int i=0;i<n;i++) cin>>Node[i].x>>Node[i].y;sort(Node,Node+n,cmp);int res=0;bool flag=false;for(int i=0;i<n;i++){int j=i,r=-1e9;while(j<n&&Node[j].x<=st)//找到最大的右端點{r=max(r,Node[j].y);j++;}if(r<st)//說明r沒有更新,說明這兩段沒有公共部分,故不能覆蓋{res=-1;break;}res++;if(r>=ed)//覆蓋完了{flag=true;break;}st=r;//更新i=j-1;}if(!flag) cout<<-1<<endl;else cout<<res<<endl;return 0; } #include<bits/stdc++.h> using namespace std; vector< pair<int,int> > ve; int n,l,r,st,ed; int main(void) {cin>>st>>ed;cin>>n;while(n--) cin>>l>>r,ve.push_back({l,r});sort(ve.begin(),ve.end());int ans=0;for(int i=0;i<ve.size();i++){int j=i;bool flag=false;int temp=st;while(j<ve.size()&&ve[j].first<=temp) flag=true,st=max(st,ve[j++].second);if(flag) ans++,i=j-1;if(st>=ed) {cout<<ans<<endl;return 0;}}cout<<-1<<endl;return 0; }

148. 合并果子


https://www.acwing.com/problem/content/description/150/

方法:每次選最小的兩個合并。

小根堆做法

#include<cstdio> #include<iostream> #include<queue> using namespace std; int main(void) {priority_queue<int, vector<int>, greater<int> >heap;int n; cin>>n;while(n--){int x; cin>>x;heap.push(x);}long long int res=0;while(heap.size()>1){int a=heap.top(); heap.pop();int b=heap.top(); heap.pop();res+=a+b;heap.push(a+b);}cout<<res<<endl;return 0; }

大根堆做法

#include<cstdio> #include<queue> #include<iostream> using namespace std; int main(void) {int n; cin>>n;priority_queue<int> heap;while(n--){int x; cin>>x;heap.push(-x);}long long int res=0;while(heap.size()>1){int a=heap.top(); heap.pop();int b=heap.top(); heap.pop();res+=(-a-b);heap.push(-(-a-b));}cout<<res<<endl;return 0; }

913. 排隊打水


https://www.acwing.com/problem/content/description/915/

思路: 由于若把時間長的放在后面接水,那么就較少人等,所以排序+貪心即可。

#include<cstdio> #include<iostream> #include<algorithm> using namespace std; const int N=1e5+10; long long int a[N],s[N]; int main(void) {int n; cin>>n;for(int i=1;i<=n;i++) cin>>a[i];sort(a+1,a+n+1);long long int sum=0;for(int i=1;i<=n-1;i++) s[i]=s[i-1]+a[i],sum+=s[i];//1代表的就是第二個人的等待時間,第一個人的等待時間為零cout<<sum<<endl;return 0; }

104. 貨倉選址

https://www.acwing.com/problem/content/description/106/
選中間的位置最優

詳細的證明

#include<cstdio> #include<iostream> #include<algorithm> using namespace std; const int N=1e5+10; int a[N],sum; int main(void) {int n; cin>>n;for(int i=0;i<n;i++) cin>>a[i];sort(a,a+n);int area=a[n/2];for(int i=0;i<n;i++) sum+=abs(area-a[i]);cout<<sum<<endl;return 0; }

125. 耍雜技的牛


https://www.acwing.com/problem/content/description/127/

按其和從小到大排序

#include<cstdio> #include<iostream> #include<algorithm> using namespace std; const int N=1e5+10; struct student {int w,s; }stu[N]; bool cmp(student a,student b) {return a.w+a.s<b.w+b.s; } int main(void) {int n;cin>>n;for(int i=1;i<=n;i++) cin>>stu[i].w>>stu[i].s;sort(stu+1,stu+n+1,cmp);int ans=-1e9;int res=0;for(int i=1;i<=n;i++){ans=max(ans,res-stu[i].s);res+=stu[i].w;}cout<<ans<<endl;return 0; }

總結

以上是生活随笔為你收集整理的第六章 贪心 【完结】的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。