備用鑰匙 分情況討論的好dp

2022-08-18 22:48:27 字數 3188 閱讀 2020

你知道just odd inventions社嗎?這個公司的業務是「只不過是奇妙的發明(just odd inventions)」。這裡簡稱為joi社。

joi社有n名員工,編號從1到n。所有員工的工作時間從時刻0持續到時刻m,時刻0和時刻m的時候,所有員工都必須在公司內。

某天,出於巧合,joi社的每個員工都要出行恰好一次。員工i(1<=i<=n)在時刻si離開公司,時刻ti回到公司。同一時刻不會同時有兩名以上的員工離開或回到公司。

joi社的入口處有一扇巨大的門,員工只能通過這扇門離開或回到公司。門上掛著一把鎖,從公司內部可以任意開鎖或上鎖,但從公司外部只有持有備用鑰匙的人才能開鎖或者上鎖。時刻0時,鎖是鎖上的。

每個社員在回到公司的時候,都必須能夠進入公司。換句話說,對於任意1<=i<=n,要麼員工i持有備用鑰匙,要麼時刻ti時門是開著的,否則是不被允許的。員工回到公司的時候,或者攜帶備用鑰匙的員工離開公司的時候,可以選擇鎖門或不鎖。沒有攜帶備用鑰匙的員工離開公司的時候沒有辦法鎖門。

joi社的社長決定把備用鑰匙交給n個員工中的k個人。為了避免鑰匙的丟失,員工之間不允許借用鑰匙。此外,joi社的社長很重視時間效率,因此每個員工在離開或回到公司的時刻以外,不允許開鎖或者上鎖。

出於安全的考慮,社長希望上鎖的時間越長越好。現在他將員工出入公司的資訊和準備交給員工的鑰匙數量告訴了你,請你求出在能使所有員工回到公司的時候都能進入公司的大門的前提下,上鎖的時間最長是多少。

第一行三個空格分隔的整數n,m,k,表示joi社的員工有n個,工作時間從時刻0到時刻m,備用鑰匙有k把。

接下來n行,第i行(1<=i<=n)有兩個空格分隔的整數si,ti,表示員工i在時刻si離開公司,時刻ti回到公司。

輸出一行乙個正整數,表示上鎖時間總和的最大值。

4 20 2

3 11

5 15

6 10

12 18

13【hint】

joi社共有4名員工,工作時間為時刻0~時刻m,共有兩把備用鑰匙。

將鑰匙交予員工2和員工4,一天日程如下:

時刻0,鎖是關閉狀態

時刻3,員工1離開公司。由於員工1沒有備用鑰匙,無法鎖門。

時刻5,員工2離開公司,鎖門。

時刻6,員工3離開公司。由於員工3沒有備用鑰匙,無法鎖門。

時刻10,員工3回到公司,不鎖門。

時刻11,員工1回到公司,鎖門。

時刻12,員工4離開公司,鎖門。

時刻15,員工2回到公司,鎖門。

時刻18,員工4回到公司,鎖門。

直到時刻20為止,鎖都保持關閉狀態。上鎖的時間段為0~3,5~6,11~20,總計13時段,故答案為13。

對於20%的資料,1<=n<=20,1<=m<=10^6

對於100%的資料:

1<=n<=2000

1<=m<=10^9

1<=k對於任意i,j (1<=i<=n,1<=j<=n,i≠j),si≠sj,si≠tj,ti≠tj

填坑啦!

思考此題暴力時,很顯然地要分情況討論。我們可以畫出時間軸來,先將資料按時間排序。接下來考慮相鄰兩個時間點之間的關係即可。同樣很顯然的是有4種情況,讓我們從易到難:

1.(進,出):取這個時間段的時候,我們可以發現前後兩人都可以沒有鑰匙,也就是(無,無),所以這些時間段是可以直接加進答案裡的。

2.(進,進):對於前者可以沒有鑰匙,可是前者把門鎖了後,後者就需要有鑰匙了,也就是(無,有),可以記為後者的貢獻。

3.(出,出):和2類似的,前者出去鎖門需要鑰匙,而後者出去可以沒有鑰匙,也就是(有,無),可以記為前者的貢獻。

4.(出,進):根據前面的經驗,我們很容易發現這類情況是(有,有),可是並不能和前面一樣,因為這裡點與點不是獨立的了,要取後乙個點的貢獻的前提是前者也取。

那怎麼辦呢?因為乙個人只有進出兩種操作,所以他出現第4種情況的時候至多為2種,我們可以考慮將其連成鏈,並重新安排順序使得鏈連在一塊的同時其他資料也在其中。先假設我們完成了這個操作,很顯然的有轉移方程:f[i][j]=max( max(f[1~i-1][j-1]) , f[i-1][j-1]+w[l[i]])+c[l[i]];前者是不取第4種情況,後者是取第4種情況,而最後加的是2,3情況中單點的貢獻。

現在要做的就是打破假設,此處借鑑了一下大佬的**,也就是dfs部分,我覺得大夥自己體會會更好一點。

1 #include2 #include3 #include4 #include5 #include6 #include7 #include8

using

namespace

std;

9#define debug printf("zjyvegetable\n")

10#define int long long

11 inline int

read()

14while(isdigit(c))

15return a*b;16}

17const

int n=2e3+50,m=5e3+50;18

struct

nodeq[m];

21bool

cmp(node x,node y)

24int

n,m,k,cnt,tot,c[n],f[n][n],ans,g[n],l[n],line[n],w[n];

25bool

bz[n];

26void dfs(int

x)31

signed main()

40 sort(q+1,q+cnt+1

,cmp);

41 ans+=q[1].t+m-q[cnt].t;

42for(int i=2;i<=cnt;i++)

46else

if(q[i-1].fl==0&&q[i].fl==0)49

else

if(q[i-1].fl==1&&q[i].fl==1)52

else

56else61}

62}63 tot=n;

64for(int i=1;i<=n;i++)

65if(!bz[i])dfs(i);

66int maxn=0;67

for(int i=1;i<=n;i++)

73 maxn=max(maxn,f[i][k]);74}

75 printf("

%lld\n

",ans+maxn);

76return0;

77 }

資料分窗的討論

對於資料處理工作,資料分窗是乙個很常見的操作,以訊號取樣序列為例,通常的方式有幾種做法 1.以序列的第乙個元素為基準,按步長滑移,按視窗尺寸切分 然而序列會因為處理的方式的不同會 對頭尾部分進行一定程度的切除,會不會對最終分窗產生影響呢?下圖顯示了切除不會對最終結果 產生大影響,只是相當於刪除首尾視...

討論構造 拷貝構造的N種呼叫情況

1.先總結c 對傳參和傳返回值時構造的優化處理。總結 在c 中,傳參和傳返回值如果是引用型別,則不用呼叫拷貝建構函式。當語句為乙個表示式時,編譯器會自動優化。一般而言,呼叫幾次構造和拷貝構造,就會呼叫幾次析構函式。系統在什麼情況下會進行優化呢?當拷貝構造存在連續的賦值情況時,當多個臨時物件連續賦值。...

討論構造拷貝構造的N種呼叫情況問題

1.先總結c 對傳參和傳返回值時構造的優化處理。1 在c 中,傳參和傳返回值時,如果是引用型別,則不用呼叫拷貝建構函式,直接返回別名。當語句為乙個表示式時,編譯器會選擇優化,將建構函式與拷貝構造合併。在c 中,呼叫幾次建構函式和拷貝建構函式,就會相應的呼叫幾次析構函式。2 系統在什麼情況下會進行優化...