NOIP2016 憤怒的小鳥(狀壓DP)

2021-08-27 21:32:26 字數 1560 閱讀 9334

輸入格式:

第一行包含乙個正整數 t,表示遊戲的關卡總數。

下面依次輸入這 t個關卡的資訊。每個關卡第一行包含兩個非負整數 n,m,分別表示該關卡中的小豬數量和 kiana 輸入的神秘指令型別。接下來的 n行中,第 ii 行包含兩個正實數

如果 m=0,表示kiana輸入了乙個沒有任何作用的指令。

如果 m=1,則這個關卡將會滿足:至多用

如果 m=2,則這個關卡將會滿足:一定存在一種最優解,其中有乙隻小鳥消滅了至少

保證

(我們知道三點確定乙個拋物線,此處的n<=18)

列舉兩頭豬,設座標為

於是這顯然是乙個

事實上,這個dp有可優化之處:每一次列舉的拋物線必須包含未消滅的第一頭豬!

because列舉的拋物線的順序與最優解無關,並且未消滅的豬在之後的拋物線中必須被覆蓋到至少一次,那麼與其先覆蓋其他的豬,不如直接先覆蓋第一頭未消滅的豬,這對答案是沒有影響的。因此,每一次轉移只需要列舉能覆蓋第一頭未消滅的豬的拋物線即可。

改變了轉移之後,時間複雜度變為

#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include //#include //#include #define mp(a,b) make_pair(a,b)

#define pb(a) push_back(a)

#define size(a) ((int)a.size())

#define len(a) ((int)a.length())

#define for(i,a,b) for(int i=(a);i

#define fi first

#define se second

using namespace std;

templateinline bool upmin(t &x,t y)

int g[maxn][maxn],s[maxn],f[(1<=0) continue; double b=y[i]/x[i]-a*x[i];

for (int k=1;k<=n;k++) g[i][j]+=s[k-1]*(check(a*x[k]+b,y[k]/x[k]));

}for (int i=0;i<=s[n]-1;i++)

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

if (!(i&s[j-1]))

printf("%d\n",f[s[n]-1]);

}return 0;

}

Noip2016 憤怒的小鳥(狀壓DP)

題意大概就是座標系上第一象限上有n只豬,每次可以構造一條經過原點且開口向下的拋物線,拋物線可能會經過某一或某些豬,求使所有豬被至少經過一次的拋物線最少數量。原題中還有乙個特殊指令m,對於正解並沒有什麼卵用,第一行乙個數t,表示資料組數 對於每組資料,第一行2個整數n,m,接下來n行每行2個正實數想x...

NOIP 2016 憤怒的小鳥

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

NOIP2016 憤怒的小鳥

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