codevs1409 攔截飛彈2

2022-05-08 05:36:12 字數 2568 閱讀 3270

【問題描述】

一場戰爭正在 a 國與 b 國之間如火如荼的展開。

b 國憑藉其強大的經濟實力開發出了無數的遠端攻擊飛彈,b 國的領導人希望,通過這些飛彈直接毀滅 a 國的指揮部,從而取得戰鬥的勝利!當然,a 國人民不會允許這樣的事情發生,所以這個世界上還存在攔截飛彈。

現在,你是一名 a 國負責飛彈攔截的高階助理。b 國的飛彈有效的形成了三維立體打擊,我們可以將這些飛彈的位置抽象三維中間的點(大小忽略),為了簡單起見,我們只考慮乙個瞬時的狀態,即他們靜止的狀態。

攔截飛彈設計非常精良,可以精準的引爆對方飛彈而不需要自身損失,但是 a 國面臨的乙個技術難題是,這些飛彈只懂得直線上公升。精確的說,這裡的直線上昇指 xyz 三維座標單調上公升。給所有的 b 國飛彈按照 1 至 n 標號,一枚攔截飛彈可以打擊的物件可以用乙個 xyz 嚴格單調上公升的序列來表示,例如:b 國飛彈位置:(0, 0, 0) (1, 1, 0) (1, 1, 1), (2, 2, 2)乙個合法的打擊序列為:乙個不合法的打擊序列為

a 國領導人將乙份飛彈位置的清單交給你,並且向你提出了兩個最簡單不過的問題(假裝它最簡單吧):

1.一枚攔截飛彈最多可以摧毀多少 b 國的飛彈?

2.最少使用多少攔截飛彈才能摧毀 b 國的所有飛彈?

不管是為了個人榮譽還是國家容易,更多的是為了飯碗,你,都應該好好的把這個問題解決掉!

【輸入檔案】

第一行乙個整數 n 給出 b 國飛彈的數目。

接下來 n 行每行三個非負整數 xi, yi, zi 給出乙個飛彈的位置,你可以假定任意兩個飛彈不會出現在同一位置。

【輸出檔案】

輸出檔案有且僅有兩行。

第一行輸出乙個整數 p,表示一枚攔截飛彈之多能夠摧毀的飛彈數。

第二行輸出乙個整數 q,表示至少需要的攔截飛彈數目。

【輸入輸出樣例】輸入4

0 0 0

1 1 0

1 1 1

2 2 2輸出3

2【資料範圍】

所有的座標都是[0,10 6 ]的整數

對於 30%的資料滿足 n < 31

對於 50%的資料滿足 n < 101

對於 100%的資料滿足 n < 1001

正解:dp+二分圖最大匹配

解題報告:

第一問直接dp,第二問考慮題目求得是乙個最小路徑覆蓋,那麼我們可以證明最小路徑覆蓋(最小路徑數)等於總點數n-最大匹配數。因為假設都沒有匹配,那麼最小路徑覆蓋就等於n,然後每多一條邊,也就意味著路徑多拓展了一格,所以就可以減少一條路徑,那麼就可以視為路徑條數-1,所以可以大概意會到最小路徑覆蓋(最小路徑數)等於總點數n-最大匹配數,具體證明見這篇部落格,寫的非常清楚、詳細:

所以直接暴力連邊,然後跑二分圖最大匹配就可以了。

1

//it is made by jump~

2 #include 3 #include 4 #include 5 #include 6 #include 7 #include 8 #include 9 #include 10 #include 11 #include 12 #include

13using

namespace

std;

14 typedef long

long

ll;15

#define rg register

16const

int maxn = 4011;17

const

int maxm = 400011;18

intn,ans,ecnt;

19int

f[maxn],next[maxm],first[maxn],to[maxm],vis[maxn],match[maxn];

20struct

nodea[maxn];

2324 inline int

getint()

2530 inline bool cmp(node q,node qq)

31 inline void link(rg int x,rg int y)

32 inline bool dfs(rg int x,rg int

o)40}41

return

false;42

}4344 inline void

work()

47 sort(a+1,a+n+1

,cmp);

48for(rg int i=2;i<=n;i++) for(rg int j=1;jif(a[j].xif(f[j]+1>f[i]) f[i]=f[j]+1

; 49

for(rg int i=1;i<=n;i++) ans=max(ans,f[i]);

50 printf("

%d\n

",ans);

51for(rg int i=2;i<=n;i++) for(rg int j=1;jif(a[j].xn);

52 ans=0; for(rg int i=1;i<=n;i++) if(dfs(i,i)) ans++;

53 printf("

%d",n-ans);54}

5556

intmain()

57

codevs1409 攔截飛彈 2

題目鏈結 題意 給出n個三維的飛彈,每次攔截只能打x,y,z嚴格上公升的若干個飛彈,求最多能一次攔截下多少個飛彈,以及最少攔截幾次將所有飛彈全部攔截。solution 第一問直接排序後n 的dp即可。第二問我們考慮二分圖匹配,連邊後轉換模型成為最小路徑覆蓋。codevs1409 include in...

codevs 攔截飛彈 1044

題目描述 description 某國為了防禦敵國的飛彈襲擊,發展出一種飛彈攔截系統。但是這種飛彈攔截系統有乙個缺陷 雖然它的第一發炮彈能夠到達任意的高度,但是以後每一發炮彈都不能高於前一發的高度。某天,雷達捕捉到敵國的飛彈來襲。由於該系統還在試用階段,所以只有一套系統,因此有可能不能攔截所有的飛彈...

codevs1044攔截飛彈

這個題第一問是求最長下降子串行,第二問可以轉化成求最長上公升子串行,為什麼?因為我們每遇到有hi hj的情況 i j 都要再使用一枚飛彈,因為飛彈只處理hi hj的情況嘛,很好理解的吧 所以 如下 完全可以更短 include include include include using namesp...