用點最多能覆蓋多少個區間,乙個點最多只能覆蓋乙個區間
q:給定n個區間和m個點,乙個點最多只能使用一次,詢問最多有多少個區間可以被點覆蓋到?
a:首先按照區間左端點從小到大排序,點也按照從小到大排序,反向列舉每個區間,在此基礎上再反向列舉點,如果這個點在區間中,那麼答案加1,統計完就是最終答案。演算法時間複雜度為 o(n
2)
o(n^2)
o(n2
)優化:利用upper_bound o(l
ogn)
o(logn)
o(logn
)得到第乙個大於區間右端點的點,再自減(要加哨兵)就是第乙個小於等於區間右端點的點,如果這個點同時又滿足大於區間左端點,就讓答案加1,演算法時間複雜度為 o(n
long
n)
o(nlongn)
o(nlon
gn)
例如:acwing 110
#include
using
namespace std;
const
int n =
2505
;typedef pair<
int,
int> pii;
pii cow[n]
;//區間(第一關鍵字為左端點,第二為右端點),點(點的值,點的數目)
int n,m;
intmain()
sort
(cow, cow + n)
;for
(int i =
0,x, y; i < m;
++ i)
int cnt =0;
mp[0]
= mp[
1001
]= n;
for(
int i = n -
1; i >=0;
-- i)
} cout << cnt << endl;
}
q:給定兩組點設為組a,b,每組點都有兩個引數x和y,一組中的某個點 a(屬於a) 只能和另一組的某個點 b(屬於b) 匹配(當且僅當 a 的兩個引數都大於 b),若匹配成功b會得到一定的回報,不能重複匹配,詢問最大的匹配數?在此基礎上詢問最大的權值
a:一般最大帶邊權匹配問題用km演算法(要求是完全匹配),最大帶點權問題用匈牙利演算法。而此題可以利用引數的性質貪心,將兩個引數以x為第一關鍵字,y為第二關鍵字從大到小排序,然後從前往後列舉能獲得回報的那組點(組b),利用mutiset維護符合x上匹配條件的組a中的點,每次選擇大於等於yb的那個點就是最優演算法。
acwing127
#include
using
namespace std;
const
int n =
1e5+5;
struct machine
}a[n]
;struct task
}b[n]
;int n,m;
intmain()
for(
int i =
0; i < m;
++ i)
sort
(a,a+n)
;sort
(b,b+m)
; multiset<
int>set;
int cnt =0;
long
long sum =0;
for(
int i =
0, j =
0; i < m;
++ i)
} cout << cnt <<
" "<< sum << endl;
}return0;
}
q:給定n個區間,詢問最少可以合併成多少個區間,兩個區間能合併當且僅當區間沒有交集(包括端點)。
a:貪心,演算法的時間複雜度為o(n
logn
)o(nlogn)
o(nlog
n)1.按區間左端點排序
2.用小根堆維護當前區間最後乙個區間的右端點,即最小的右端點
3.從前往後列舉區間,如果當前區間的左端點小於最小的右端點,說明要新加乙個區間,否則直接更新最小右端點即可。
acwing 111
/*
類似區間合併
*/#include
using
namespace std;
const
int n =
5e4+5;
typedef pair<
int,
int> pii;
typedef pairint> piii;
int n;
piii a[n]
;int id[n]
;struct node};
intmain()
sort
(a+1
,a+1
+n);
///按照區間左端點排序
int ans =0;
priority_queueq;
///過載小根堆
for(
int i=
1;i<=n;
++i));
id[a[i]
.second]
= ans;
}else);
id[a[i]
.second]
= idx;}}
cout << ans << endl;
for(
int i=
1;i<=n;
++i) cout << id[i]
<< endl;
}
最少用多少個點能覆蓋全部區間,乙個點可以同時覆蓋多個區間
思路:1.先求每個點能被探測到的雷達放置區間
2.按照右端點從小到大排序
3.從前往後列舉每個區間,如果當前區間包含最後乙個點則繼續,否則選取當前區間的右端點作為新的點
#include
using
namespace std;
const
int n =
1005
;typedef pair<
double
,double
> pdd;
typedef pair<
int,
int> pii;
int n,d;
pii p[n]
;pdd a[n]
;int x,y;
intmain()
double t =
sqrt
(d*d - y*y)
; a[i]
.first = x+t, a[i]
.second = x-t;
}double k =
-dbl_max;
int ans =0;
sort
(a+1
,a+1
+n);
for(
int i=
1;i<=n;
++i)
} cout << ans << endl;
}
ACM演算法之貪心演算法
acm演算法之貪心演算法 一般使用貪心演算法要滿足兩個條件 a.貪心選擇性質 可通過做區域性最優 貪心 選擇來達到全域性最優解。貪心選擇性質 這是貪心演算法與動態規劃的區別 b.最優子結構性質 問題的最優解包含了子問題的最優解。貪心演算法的基本思想 找出整體當中每個小的區域性的最優解,並且將所有的這...
ACM 貪心演算法
這是大學期間acm校賽時我出的一道題,考貪心演算法,沒有牽涉複雜的資料結構,有題目加源 贏取最多最有價值的禮物 problem description 五一期間到長沙烈士公園玩,走進去之後,發現許多人在圍在一起玩一種遊戲,遊戲規則是 給你m個環,用乙個環可以套住乙個禮物,同時丟擲時要花費一秒鐘的時間...
ACM 貪心演算法
acm 貪心演算法 在求最優解問題的過程中,依據某種貪心標準,從問題的初始狀態出發,直接去求每一步的最優解,通過若干次的貪心選擇,最終得出整個問題的最優解,這種求解方法就是貪心演算法。從貪心演算法的定義可以看出,貪心演算法不是從整體上考慮問題,它所做出的選擇只是在某種意義上的區域性最優解,而由問題自...