刷题总结——愤怒的小鸟(NOIPDAY2T3)
題目:
題目背景
NOIP2016?提高組?Day2?T3
題目描述
Kiana?最近沉迷于一款神奇的游戲無法自拔。簡單來說,這款游戲是在一個平面上進行的。
有一架彈弓位于?(0,0)?處,每次?Kiana?可以用它向第一象限發射一只紅色的小鳥,小鳥們的飛行軌跡均為形如?y=ax2+bx?的曲線,其中?a,b?是?Kiana?指定的參數,且必須滿足?a<0。
當小鳥落回地面(即x軸)時,它就會瞬間消失。
在游戲的某個關卡里,平面的第一象限中有?n?只綠色的小豬,其中第?i?只小豬所在的坐標為?(xi,yi)?。
如果某只小鳥的飛行軌跡經過了(xi,yi),那么第?i?只小豬就會被消滅掉,同時小鳥將會沿著原先的軌跡繼續飛行;
如果一只小鳥的飛行軌跡沒有經過(xi,yi),那么這只小鳥飛行的全過程就不會對第?i?只小豬產生任何影響。
例如,若兩只小豬分別位于?(1,3)?和?(3,3)?,Kiana?可以選擇發射一只飛行軌跡為?y=-x2+4x?的小鳥,這樣兩只小豬就會被這只小鳥一起消滅。
而這個游戲的目的,就是通過發射小鳥消滅所有的小豬。
這款神奇游戲的每個關卡對?Kiana?來說都很難,所以?Kiana?還輸入了一些神秘的指令,使得自己能更輕松地完成這個游戲。這些指令將在【輸入格式】中詳述。
假設這款游戲一共有?T?個關卡,現在?Kiana?想知道,對于每一個關卡,至少需要發射多少只小鳥才能消滅所有的小豬。由于她不會算,所以希望由你告訴她。
輸入格式
下面依次輸入這?T?個關卡的信息。每個關卡第一行包含兩個非負整數?n,m?,分別表示該關卡中的小豬數量和?Kiana?輸入的神秘指令類型。接下來的?n?行中,第?i?行包含兩個正實數?xi,yi?,表示第?i?只小豬坐標為?(xi,yi)。數據保證同一個關卡中不存在兩只坐標完全相同的小豬。
如果?m=0,表示?Kiana?輸入了一個沒有任何作用的指令。
如果?m=1?,則這個關卡將會滿足:至多用??只小鳥即可消滅所有小豬。
如果?m=2?,則這個關卡將會滿足:一定存在一種最優解,其中有一只小鳥消滅了至少??只小豬。
保證?1≤n≤18,0≤m≤2,0<xi,yi<10,輸入中的實數均保留到小數點后兩位。
上文中,符號??分別表示對?c?向上取整和向下取整,例如:
????
輸出格式
對每個關卡依次輸出一行答案。
輸出的每一行包含一個正整數,表示相應的關卡中,消滅所有小豬最少需要的小鳥數量。
樣例數據 1
輸入 [復制]
?
2?2 0?
1.00 3.00?
3.00 3.00?
5 2?
1.00 5.00?
2.00 8.00?
3.00 9.00?
4.00 8.00?
5.00 5.00
輸出
1?1
樣例數據 2
輸入 [復制]
?
3?2 0?
1.41 2.00?
1.73 3.00?
3 0?
1.11 1.41?
2.34 1.79?
2.98 1.49?
5 0?
2.72 2.72?
2.72 3.14?
3.14 2.72?
3.14 3.14?
5.00 5.00
輸出
2?2?
3
樣例數據 3
輸入 [復制]
?
1?10 0?
7.16 6.28?
2.02 0.38?
8.33 7.78?
7.68 2.09?
7.46 7.86?
5.77 7.44?
8.24 6.72?
4.42 5.11?
5.42 7.79?
8.15 4.99
輸出
6備注
【樣例1說明】
這組數據中一共有兩個關卡。
第一個關卡與【問題描述】中的情形相同,2?只小豬分別位于?(1.00,3.00)?和?(3.00,3.00)?,只需發射一只飛行軌跡為?y=-x2+4x?的小鳥即可消滅它們。
第二個關卡中有?5?只小豬,但經過觀察我們可以發現它們的坐標都在拋物線?y=-x2+6x?上,故?Kiana?只需要發射一只小鳥即可消滅所有小豬。
【數據規模與約定】
數據的一些特殊規定如下表:
題解:
狀壓dp,dp[s]表示在打到s狀態的豬下至少需要多少只小鳥。g[i][j]表示打到了第i和j只豬的情況下可以達到的狀態,預處理即可,得到dp方程:
dp[s|g[i][j]]=min{dp[s|g[i][j]],dp[s]+1};
代碼:
#include<iostream> #include<cstdio> #include<cstdlib> #include<cmath> #include<ctime> #include<cctype> #include<string> #include<cstring> #include<algorithm>using namespace std; const int M=50; const int inf=0x3f3f3f3f;struct point {double x;double y; }p[M];int T,n,m,g[M][M],s=0; int bit[21],dp[2000000]; double A,B;inline void calc(int i,int j) {double a1=p[i].x*p[i].x,b1=p[i].x,c1=p[i].y; double a2=p[j].x*p[j].x,b2=p[j].x,c2=p[j].y;if(b1==b2) return;A=(c1*b2-c2*b1)/(a1*b2-a2*b1);B=(c1*a2-c2*a1)/(b1*a2-a1*b2);if(A>=0) return; for(int k=1;k<=n;k++)if(abs(A*p[k].x*p[k].x+B*p[k].x-p[k].y)<=1e-7)g[i][j]=g[i][j]|(1<<(k-1)); } inline void pre() {for(int i=1;i<=n;i++)for(int j=1;j<=n;j++){if(i==j){ g[i][j]=1<<(i-1);continue;}else calc(i,j);} }int main() {//freopen("a.in","r",stdin);//freopen("a.out","w",stdout);bit[0]=1;for(int i=1;i<=20;i++)bit[i]=bit[i-1]*2;scanf("%d",&T);while(T--){memset(dp,inf,sizeof(dp));memset(g,0,sizeof(g));scanf("%d%d",&n,&m); for(int i=1;i<=n;i++)scanf("%lf%lf",&p[i].x,&p[i].y);pre();dp[0]=0;s=(1<<n)-1;for(int i=0;i<=s;i++)for(int j=1;j<=n;j++)for(int k=1;k<=n;k++)dp[i|g[j][k]]=min(dp[i|g[j][k]],dp[i]+1);cout<<dp[s]<<endl;}return 0; }?
轉載于:https://www.cnblogs.com/AseanA/p/7250453.html
總結
以上是生活随笔為你收集整理的刷题总结——愤怒的小鸟(NOIPDAY2T3)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: HDU 1221: Cube
- 下一篇: mysql数据库外连