洛谷 P2831 憤怒的小鳥

2021-10-07 07:08:30 字數 3584 閱讀 6380

狀壓dp

\text

dp

n≤18

n\leq 18

n≤18

,不是暴搜就是狀壓,因為我jio

jioji

o得狀壓會比較好理解,所以就寫一篇狀壓的題解叭

首先我們要預處理出經過任意兩點的拋物線可以擊中的小豬有哪些,可以用lin

e[i]

[j

]line[i][j]

line[i

][j]

來表示經過i,j

i,ji,

j的拋物線經過的小豬的集合,集合用二進位制數來表示

處理完之後就要想一想如何dp

\text

dp我們設dp[

s]

dp[s]

dp[s

]表示消滅集合s

ss內所有小豬所用的最少的小鳥數

顯然d p[

0]=0

dp[0]=0

dp[0]=

0,因為沒有豬當然用不到鳥

假設當前的狀態為s

ss,拋物線為經過i,j

i,ji,

j點的拋物線,這條拋物線打掉的小豬的狀態為lin

e[i]

[j

]line[i][j]

line[i

][j]

,那麼有

d p[

s∣li

ne[i

][j]

]=

min⁡(d

p[s∣

line

[i][

j]],

dp[s

]+1)

dp[s|line[i][j]] = \min(dp[s|line[i][j]],dp[s] + 1)

dp[s∣l

ine[

i][j

]]=min(d

p[s∣

line

[i][

j]],

dp[s

]+1)

其中s ∣l

ine[

i][j

]s|line[i][j]

s∣line

[i][

j]表示當前狀態s

ss在增加了經過i,j

i,ji,

j點的這條拋物線之後能打到的小豬的集合,顯然要從dp[

s∣li

ne[i

][j]

]dp[s|line[i][j]]

dp[s∣l

ine[

i][j

]]和d p[

s]+1

dp[s]+1

dp[s]+

1中取最小

時間複雜度o(t

n22n

)o(tn^22^n)

o(tn22

n)o(能過才怪),在洛谷上吸氧(o2o2

o2)可以過

隨意選擇s

ss內的乙隻小豬j

jj,那麼j

jj最後一定會被乙隻小鳥消滅,所以我們固定住這只小豬j

jj,只列舉k

kk轉移

更詳細見athousandsuns的題解

時間複雜度o(t

n2n)

o(tn2^n)

o(tn2n

),穩了

/*

author:loceaner

*/#include

#include

#include

#include

#include

#define eps (1e-6)

using

namespace std;

const

int a =

5e5+11;

const

int b =

1e6+11;

const

int mod =

1e9+7;

const

int inf =

0x3f3f3f3f

;inline

intread()

int n, m, num, line[20]

[20], dp[b]

;struct pig p[a]

;//豬豬結構體

bool

cmp(pig a, pig b)

struct line };

inline line get

(pig a, pig b)

intmain()

int u =(1

<< n)-1

;//全集

dp[0]

=0;//沒豬當然是0

for(

int i =

1; i <= n; i++

)//快樂地dp吧!

for(

int j =

1; j <= n; j++

)for

(int k =

0; k <= u; k++

) dp[k | line[i]

[j]]

=min

(dp[k | line[i]

[j]]

, dp[k]+1

);cout << dp[u]

<<

'\n';}

return0;

}

/*

author:loceaner

*/#include

#include

#include

#include

#include

#define eps (1e-6)

using

namespace std;

const

int a =

5e5+11;

const

int b =

1e6+11;

const

int mod =

1e9+7;

const

int inf =

0x3f3f3f3f

;inline

intread()

int n, m, num, line[20]

[20], dp[b]

, must[b]

;struct pig p[a]

;bool

cmp(pig a, pig b)

struct line };

inline line get

(pig a, pig b)

intmain()

int t =

read()

;while

(t--

)int u =(1

<< n)-1

; dp[0]

=0;for

(int i =

0; i <= u; i++

) cout << dp[u]

<<

'\n';}

return0;

}

洛谷 P2831 憤怒的小鳥

kiana最近沉迷於一款神奇的遊戲無法自拔。簡單來說,這款遊戲是在乙個平面上進行的。有一架彈弓位於 0,0 處,每次kiana可以用它向第一象限發射乙隻紅色的小鳥,小鳥們的飛行軌跡均為形如 當小鳥落回地面 即x軸 時,它就會瞬間消失。在遊戲的某個關卡裡,平面的第一象限中有n只綠色的小豬,其中第i只小...

洛谷p2831憤怒的小鳥

原題 每個豬的位置不同,所以不能簡單的表示出狀態,all i 表示第i個拋物線打掉了哪些豬,其值本身儲存狀態 二進位制 只需要找所有有用的拋物線,然後狀壓f i 表示i狀態下最少用掉的鳥,轉移方程見 其中的m可以用來優化。雖然長,但是比較好懂。include include include incl...

洛谷P2831 憤怒的小鳥

題目 狀壓dp。直接列舉二進位制數表示當前豬有沒有被消滅的狀態。最終答案的幾條拋物線必定至少撞到乙個豬。而且兩頭豬確定一條拋物線,可以列舉兩頭豬,分別求出他們的拋物線所消滅豬的狀態,然後可以用類似揹包的方法轉移dp。有方程 dp i 當前拋物線的狀態 min dp i 當前拋物線的狀態 dp i 1...