1. 程式人生 > >【洛谷P2831】[NOIP2016]憤怒的小鳥

【洛谷P2831】[NOIP2016]憤怒的小鳥

string href oid span code pre amp scan 不可

憤怒的小鳥

題目鏈接

搜索是比較好想的,直接dfs就行了

我們可以知道兩只豬確定一條拋物線

依次處理每一只豬,有以下幾種方法:

1.先看已經建立的拋物線是否能打到這只豬

2.若1不可行,將這只豬與之前單著的豬配對,建拋物線

3.將這只豬單著,等待以後配對(若配不上,直接建一個只打一頭豬的拋物線)

代碼:

 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdio>
 4 using namespace std;
 5 #define N 20
 6 #define eps 1e-6
 7 #define
INF 0x3f3f3f3f 8 #define fabs(x) ((x)>0?(x):-(x)) 9 #define reset(a) memset(a,0,sizeof(a)) 10 #define check(p,q,i) fabs(p*p*a[i]+p*b[i]-q)<=eps 11 int T,n,m,ans,cnt1,cnt2,dealta; 12 double X[N],Y[N],a[N],b[N]; 13 double x[N],y[N]; 14 bool used[N]; 15 void dfs(int t){ 16 if(cnt1+cnt2-dealta>=ans) return
; //剪枝 17 if(t==n+1){ 18 ans=cnt1+cnt2-dealta; 19 return; 20 } 21 bool flag=0; 22 for(int i=1;i<=cnt1;i++) 23 if(check(X[t],Y[t],i)){ flag=1;break; } //若以前建的拋物線能打到這頭豬 24 if(flag){ dfs(t+1); return; } //直接搜下一個 25 for(int i=1;i<=cnt2;i++) 26 if
(!used[i]){ 27 if(fabs(X[t]-x[i])<=eps) continue; 28 double A=(X[t]*y[i]-x[i]*Y[t])/(X[t]*x[i]*x[i]-X[t]*X[t]*x[i]); //兩豬確定一條拋物線 29 double B=(Y[t]-A*X[t]*X[t])/X[t]; 30 if(A>=0) continue; //拋物線開口不能朝上 31 used[i]=1; dealta++; //used[i]置為1相當於第i個單著的豬刪去,cnt2-dealta為單著的豬的總數 32 a[++cnt1]=A; b[cnt1]=B; 33 dfs(t+1); 34 cnt1--; //回溯 35 used[i]=0; dealta--; 36 } 37 x[++cnt2]=X[t]; y[cnt2]=Y[t]; 38 dfs(t+1); 39 cnt2--; 40 } 41 int main(){ 42 scanf("%d",&T); 43 while(T--){ 44 reset(X); reset(Y); 45 ans=INF; cnt1=cnt2=dealta=0; 46 reset(x); reset(y); reset(used); 47 scanf("%d%d",&n,&m); 48 for(int i=1;i<=n;i++) 49 scanf("%lf%lf",&X[i],&Y[i]); //讀入坐標 50 dfs(1); printf("%d\n",ans); 51 } 52 return 0; 53 }

【洛谷P2831】[NOIP2016]憤怒的小鳥