C++實現(xiàn)貪心算法的示例詳解
區(qū)間問題
區(qū)間選點
給定 N 個閉區(qū)間 [ai,bi],請你在數(shù)軸上選擇盡量少的點,使得每個區(qū)間內(nèi)至少包含一個選出的點。
輸出選擇的點的最小數(shù)量。
位于區(qū)間端點上的點也算作區(qū)間內(nèi)。
輸入格式
第一行包含整數(shù) N,表示區(qū)間數(shù)。
接下來 N 行,每行包含兩個整數(shù) ai,bi,表示一個區(qū)間的兩個端點。
輸出格式
輸出一個整數(shù),表示所需的點的最小數(shù)量。
數(shù)據(jù)范圍
1≤N≤1e5,
−1e9≤ai≤bi≤1e9
先對右端點進(jìn)行排序,有交集的區(qū)間進(jìn)行右端點的更新,沒有交集則點數(shù)+1。
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
struct node{
int a,b;
bool operator<(const node&w)const {
return b<w.b;}
}range[N];
int main(){
int n;
cin>>n;
int a,b;
for(int i=0;i<n;i++){
cin>>a>>b;
range[i]={a,b};
}
sort(range, range+n);
int s=-2e9,cnt=0;
for(int i=0;i<n;i++){
if(s<range[i].a){
cnt++;
s=range[i].b;
}
}
cout<<cnt;
return 0;
}
最大不相交區(qū)間數(shù)量
給定 N 個閉區(qū)間 [ai,bi],請你在數(shù)軸上選擇若干區(qū)間,使得選中的區(qū)間之間互不相交(包括端點)。
輸出可選取區(qū)間的最大數(shù)量。
輸入格式
第一行包含整數(shù) N,表示區(qū)間數(shù)。
接下來 N 行,每行包含兩個整數(shù) ai,bi,表示一個區(qū)間的兩個端點。
輸出格式
輸出一個整數(shù),表示可選取區(qū)間的最大數(shù)量。
數(shù)據(jù)范圍
1≤N≤1e5,
−1e9≤ai≤bi≤1e9
先對右端點進(jìn)行排序,有交集的區(qū)間進(jìn)行右端點的更新,沒有交集則點數(shù)+1。
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
struct node{
int a,b;
bool operator<(const node&w)const{
return b<w.b;
}
}range[N];
int main(){
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
int n;
cin>>n;
for(int i=0;i<n;i++){
int a,b;
cin>>a>>b;
range[i]={a,b};
}
int res=0,s=-2e9;
sort(range,range+n);
for(int i=0;i<n;i++){
if(range[i].a>s){
s=range[i].b;
res++;
}
}
cout<<res;
return 0;
}
區(qū)間分組
給定 N 個閉區(qū)間 [ai,bi],請你將這些區(qū)間分成若干組,使得每組內(nèi)部的區(qū)間兩兩之間(包括端點)沒有交集,并使得組數(shù)盡可能小。
輸出最小組數(shù)。
輸入格式
第一行包含整數(shù) N,表示區(qū)間數(shù)。
接下來 N 行,每行包含兩個整數(shù) ai,bi,表示一個區(qū)間的兩個端點。
輸出格式
輸出一個整數(shù),表示最小組數(shù)。
數(shù)據(jù)范圍
1≤N≤1e5,
−1e9≤ai≤bi≤1e9
先區(qū)分左右端點進(jìn)行排序,再遍歷取左右 端點未抵消的最大值。
#include<bits/stdc++.h>
using namespace std;
const int N = 100010;
int n;
int b[2 * N], idx;
int main() {
cin >> n;
for (int i = 0; i < n; i++) {
int l, r;
cin >> l >> r;
b[idx++] = l * 2;
b[idx++] = r * 2 + 1;//用奇偶性區(qū)分左右端點
}
sort(b, b + idx);
int res = 1, t = 0;
for (int i = 0; i < idx; i++) {
if (b[i] % 2 == 0)t++;
else t--;
res = max(res, t);
}
cout << res;
return 0;
}
優(yōu)先隊列做法。
#include<bits/stdc++.h>
using namespace std;
const int N = 100010;
struct Range {
int l, r;
bool operator <(const Range& w)const {
return l < w.l;
}
}range[N];
int n;
int main() {
cin >> n;
for (int i = 0; i < n; i++) {
int l, r;
cin >> l >> r;
range[i] = { l,r };}
sort(range, range + n);
int res = 0,ed=-2e9;
priority_queue<int, vector<int>, greater<int>>heap;
for (int i = 0; i < n; i++) {
auto r = range[i];
if (heap.empty() || heap.top() >= r.l)heap.push(r.r);
else {
int t = heap.top();
heap.pop();
heap.push(r.r);
}
}
cout << heap.size();
return 0;
}區(qū)間覆蓋
給定 N 個閉區(qū)間 [ai,bi] 以及一個線段區(qū)間 [s,t],請你選擇盡量少的區(qū)間,將指定線段區(qū)間完全覆蓋。
輸出最少區(qū)間數(shù),如果無法完全覆蓋則輸出 −1。
輸入格式
第一行包含兩個整數(shù) s 和 t,表示給定線段區(qū)間的兩個端點。
第二行包含整數(shù) N,表示給定區(qū)間數(shù)。
接下來 N 行,每行包含兩個整數(shù) ai,bi,表示一個區(qū)間的兩個端點。
輸出格式
輸出一個整數(shù),表示所需最少區(qū)間數(shù)。
如果無解,則輸出 −1。
數(shù)據(jù)范圍
1≤N≤1e5,
−1e9≤ai≤bi≤1e9,
−1e9≤s≤t≤1e9
#include<bits/stdc++.h>
using namespace std;
const int N = 100010;
struct Range {
int l, r;
bool operator <(const Range& w)const {
return l < w.l;
}
}range[N];
int main() {
int n;
int st, ed;
cin >> st >> ed;
cin >> n;
for (int i = 0; i < n; i++) {
int l, r;
cin >> l >> r;
range[i] = { l,r };
}
sort(range, range + n);
int res = 0;
bool sc = false;
for (int i = 0; i < n; i++) {
int j = i, r = -2e9;
while (j < n && range[j].l <= st) {
r = max(r, range[j].r);
j++;
}
if (r < st) {
res = -1;
break;
}
res++;
if (r >= ed) {
sc = true;
break;
}
i = j-1;
st = r;
}
if (!sc)cout << -1;
else cout << res;
return 0;
}Huffman樹
合并果子
在一個果園里,達(dá)達(dá)已經(jīng)將所有的果子打了下來,而且按果子的不同種類分成了不同的堆。
達(dá)達(dá)決定把所有的果子合成一堆。
每一次合并,達(dá)達(dá)可以把兩堆果子合并到一起,消耗的體力等于兩堆果子的重量之和。
可以看出,所有的果子經(jīng)過 n−1 次合并之后,就只剩下一堆了。
達(dá)達(dá)在合并果子時總共消耗的體力等于每次合并所耗體力之和。
因為還要花大力氣把這些果子搬回家,所以達(dá)達(dá)在合并果子時要盡可能地節(jié)省體力。
假定每個果子重量都為 1,并且已知果子的種類數(shù)和每種果子的數(shù)目,你的任務(wù)是設(shè)計出合并的次序方案,使達(dá)達(dá)耗費的體力最少,并輸出這個最小的體力耗費值。
例如有 3 種果子,數(shù)目依次為 1,2,9。
可以先將 1、2 堆合并,新堆數(shù)目為 3,耗費體力為 3。
接著,將新堆與原先的第三堆合并,又得到新的堆,數(shù)目為 12,耗費體力為 12。
所以達(dá)達(dá)總共耗費體力=3+12=15。
可以證明 15 為最小的體力耗費值。
輸入格式
輸入包括兩行,第一行是一個整數(shù) n,表示果子的種類數(shù)。
第二行包含 n 個整數(shù),用空格分隔,第 i 個整數(shù) ai 是第 i 種果子的數(shù)目。
輸出格式
輸出包括一行,這一行只包含一個整數(shù),也就是最小的體力耗費值。
輸入數(shù)據(jù)保證這個值小于 231。
數(shù)據(jù)范圍
1≤n≤10000,
1≤ai≤20000
只需要用優(yōu)先隊列先取出兩個,再插入一個,直至最后剩下一個。
#include<iostream>
#include<algorithm>
#include<queue>
#include<bits/stdc++.h>
using namespace std;
int main() {
int n;
cin>>n;
priority_queue<int, vector<int>, greater<int>>heap;
while (n--) {
int x;
cin >> x;
heap.push(x);
}
int res = 0;
while (heap.size() > 1) {
int a = heap.top();
heap.pop();
int b = heap.top();
heap.pop();
int c = a + b;
heap.push(c);
res += c;
}
cout << res;
return 0;
}
排序不等式
排隊打水
有 n 個人排隊到 1 個水龍頭處打水,第 i 個人裝滿水桶所需的時間是 ti,請問如何安排他們的打水順序才能使所有人的等待時間之和最???
輸入格式
第一行包含整數(shù) n。
第二行包含 n 個整數(shù),其中第 i 個整數(shù)表示第 i 個人裝滿水桶所花費的時間 ti。
輸出格式
輸出一個整數(shù),表示最小的等待時間之和。
數(shù)據(jù)范圍
1≤n≤1e5,
1≤ti≤1e4
值正序,下標(biāo)倒序相乘得到最小值
#include<bits/stdc++.h>
using namespace std;
const int N = 100010;
int a[N];
int main() {
int n;
cin >> n;
for (int i = 0; i < n; i++) {
cin >> a[i];
}
sort(a, a + n);
int x=n;
long long res=0;
for (int i = 0; i < n; i++) {
res += a[i] * (x - 1);
x--;
}
cout << res;
return 0;
}
絕對值不等式
貨艙選址
在一條數(shù)軸上有 N 家商店,它們的坐標(biāo)分別為 A1∼AN。
現(xiàn)在需要在數(shù)軸上建立一家貨倉,每天清晨,從貨倉到每家商店都要運送一車商品。
為了提高效率,求把貨倉建在何處,可以使得貨倉到每家商店的距離之和最小。
輸入格式
第一行輸入整數(shù) N。
第二行 N 個整數(shù) A1∼AN。
輸出格式
輸出一個整數(shù),表示距離之和的最小值。
數(shù)據(jù)范圍
1≤N≤100000,
0≤Ai≤40000
只需統(tǒng)計各點到中位數(shù)的距離之和。
#include <bits/stdc++.h>
using namespace std;
const int N=100100;
int a[N],n,i,ans,sum;
int main()
{
cin>>n;
for (i=1;i<=n;i++)
cin>>a[i];
sort(a+1,a+1+n);//排序
int sm=a[n/2+1];//中位數(shù)
for (i=1;i<=n;i++)
ans=ans+abs(a[i]-sm);//統(tǒng)計和中位數(shù)之間的差
cout<<ans;
return 0;
}以上就是C++實現(xiàn)貪心算法的示例詳解的詳細(xì)內(nèi)容,更多關(guān)于C++ 貪心算法的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
C語言 鏈?zhǔn)蕉鏄浣Y(jié)構(gòu)詳解原理
二叉樹的鏈?zhǔn)酱鎯Y(jié)構(gòu)是指,用鏈表來表示一棵二叉樹,即用鏈來指示元素的邏輯關(guān)系。通常的方法是鏈表中每個結(jié)點由三個域組成,數(shù)據(jù)域和左右指針域,左右指針分別用來給出該結(jié)點左孩子和右孩子所在的鏈結(jié)點的存儲地址2021-11-11

