題解 P2831 憤怒的小鳥

2022-05-07 21:27:09 字數 1195 閱讀 5355

題目鏈結

題目大意:第一象限內有\(n\)個點(\(n \leq 18\)),求最少要多少條形如\(y=ax^2+bx \quad a<0,a,b, \in r\) 的拋物線才能覆蓋所有點

狀壓\(dp\)

分析:\(n\)的資料範圍很小,因此我們可以考慮狀壓\(dp\),填表法不好做我們可以用刷表法

用\(f[s]\)表示覆蓋集合\(s\)內點的最小代價

顯然\(f[0]= 0\)

\(f[s|line[i][j]] = min\\)其中\(line[i][j]\)表示經過\(i,j\)兩點的拋物線可以覆蓋的點的集合

\(f[s | 1<

這樣單次複雜度\(o(2^nn^2)\),有點懸

狀態的\(2^n\)不能消掉我們從轉移入手

原來每次列舉所有沒有被覆蓋的點是\(n^2\)的,我們固定其中乙個點為沒有被覆蓋的點中編號最小的,這樣轉移就是\(n\)的

為什麼這樣是對的?因為我們最終要求的是覆蓋所有的點,當前狀態不覆蓋最小的點也會被下乙個狀態覆蓋,所以可以直接欽定乙個點

這題樣例都卡精度,醉了

#include #include #include #include using namespace std;

const int maxn = 23;

typedef long double type;

const type eps = 1e-7;

struct posval[maxn];

int t,n,m,dp[1 << maxn],lowbit[1 << maxn],line[maxn][maxn];//lowbit表示最小的為0的點的編號

inline bool cmp(type a,type b)

void gauss(type &x,type &y,type a1,type b1,type c1,type a2,type b2,type c2)

inline void solve()

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

cout << dp[(1 << n) - 1] << '\n';

}int main()

cin >> t;

while(t--)solve();

return 0;

}

P2831 憤怒的小鳥 題解

p2831 憤怒的小鳥 我們注意到 n 18 所以考慮狀壓 dp或者暴力。定義 f s 表示 s 為 1 位置上的豬已經被打掉的最少次數 顯然我們能很容易的得到轉移方程 dp 0 0 dp s line i j min dp s 1 dp s 1 i 1 min dp s 1 考慮如何優化 因為我們...

P2831 憤怒的小鳥

kiana最近沉迷於一款神奇的遊戲無法自拔。簡單來說,這款遊戲是在乙個平面上進行的。有一架彈弓位於 0,0 處,每次kiana可以用它向第一象限發射乙隻紅色的小鳥,小鳥們的飛行軌跡均為形如y ax 2 bxy ax2 bx的曲線,其中a,b是kiana指定的引數,且必須滿足a 0。當小鳥落回地面 即...

P2831 憤怒的小鳥

傳送門 看到資料範圍就知道是搜尋或狀壓dp 算了一波複雜度搜尋好像過不了極限資料 搞狀壓設 f i 表示所有豬的狀態為 i 二進位制下1表示死了,0表示沒死 時需要的最少發射次數 設 p i j 存經過第 i 只豬和第 j 只豬的拋物線經過的豬的狀態 可以 n 2 預處理出來,解方程都會吧.找到第乙...