給定乙個數軸上的 n 個區間,要求在數軸上選取最少的點使得第 i 個區間 [ai, bi] 裡至少有 ci 個點
使用差分約束系統的解法解決這道題
使用差分約束系統的解法解決這道題
使用差分約束系統的解法解決這道題
使用差分約束系統的解法解決這道題
使用差分約束系統的解法解決這道題
input
輸入第一行乙個整數 n 表示區間的個數,接下來的 n 行,
每一行兩個用空格隔開的整數 a,b 表示區間的左右端點。
1 <= n <= 50000, 0 <= ai <= bi <= 50000 並且 1 <= ci <= bi - ai+1。
output
輸出乙個整數表示最少選取的點的個數
sample input
5
3 7 3
8 10 3
6 8 1
1 3 1
10 11 1
sample output
6
本題核心內容為差分約束系統。
差分約束系統為一種特殊的n元不等式組,包含 n 個變數以及 m 個約束條件。
其中每個約束條件是由兩個其中的變數做差構成的,形如xi-xj≤ck(ck是常數)。
我們要解決的問題是:求一組解使得所有的約束條件得到滿足,否則判斷出無解。
那如何轉化呢?
通過移項,可以得到xi≤xj+ck。這個形式與dis[i]≤dis[j]+w非常相似,所以我們通過這個式子將兩者聯絡起來。
同時,因為求單源路徑都是最短路/最長路,只乙個最值,所以最終得到的答案都是等於號成立的情況。那麼,想要求最大值,跑最短路,求最小值,跑最長路。
其中,求單源最短/長路,我們選用spfa演算法,本題不存在負環等情況,所以沒有進行優化,若可能出現負環/無法到達等情況,可以利用優化的spfa/bellman演算法。
#include
#include
#include
#include
using
namespace std;
int t=
0,a=
0,b=
0,c=
0,q=
100000
,p=0
,tot=0;
int a[
50500]=
;int head[
50500
],inq[
50500
],dis[
50500];
queue<
int> q;
struct edgeedge[
160000];
void
init()
}void
spfa
(int s)
memset
(inq,0,
sizeof
(inq));
memset
(dis,-1
,sizeof
(dis));
dis[s]=0
; inq[s]=1
; q.
push
(s);
while
(!q.
empty()
)}}}
}int
main()
//記錄最大最小點
if(aedge[
++tot]
.to=b+1;
edge[tot]
.next=head[a]
; head[a]
=tot;
edge[tot]
.w=c;
}//新增邊
//繼續插邊使得相鄰sum之差總是大於等於0,小於等於1
for(
int i=q;i)spfa
(q);
printf
("%d\n"
,dis[p]);
}
最需要注意的一點是,為了控制0<=sum[i]-sum[i-1]<=1,需要在增加完所有輸入的邊之後,繼續向圖中加邊!
包含memset的標頭檔案為string.h!不要混淆,不是cstring也不是string。
可以把本題中重複出現的加邊操作寫為乙個函式,在主函式中重複呼叫它即可。
B 區間選點
數軸上有 n 個閉區間 a i,b i 取盡量少的點,使得每個區間內都至少有乙個點 不同區間內含的點可以是同乙個 第一行1個整數n n 100 第2 n 1行,每行兩個整數a,b a,b 100 乙個整數,代表選點的數目。input 21 5 4 6output 1input 31 3 2 54 6...
B 區間選點
數軸上有 n 個閉區間 a i,b i 取盡量少的點,使得每個區間內都至少有乙個點 不同區間內含的點可以是同乙個 input 第一行1個整數n n 100 第2 n 1行,每行兩個整數a,b a,b 100 output 乙個整數,代表選點的數目examples input 2 1 54 6outp...
區間選點 貪心
給定n個閉區間 ai,biai,bi 請你在數軸上選擇盡量少的點,使得每個區間內至少包含乙個選出的點。輸出選擇的點的最小數量。位於區間端點上的點也算作區間內。輸入格式 第一行包含整數n,表示區間數。接下來n行,每行包含兩個整數ai,biai,bi,表示乙個區間的兩個端點。輸出格式 輸出乙個整數,表示...