luogu2831 [NOIp2016]憤怒的小鳥 (狀壓dp)
阿新 • • 發佈:2018-09-24
type pac sin include class freopen 枚舉 ace esp
由範圍可以想到狀壓dp
兩個點(再加上原點)是可以確定一個拋物線的,除非它們解出來a>=0,在本題中是不合法的
這樣的話,我們可以預處理出由任意兩個點確定的拋物線所經過的所有的點(要特別規定一下自己和自己確定的拋物線只經過自己)
然後設狀態s表示目前已經有哪些點被擊中了,然後我們欽定這次就要打那個最小的還沒擊中的點(因為吃棗都要打的嘛),再枚舉出另一個還沒經過的點,就能得到轉移方程
$f[s|line[i][j]]=max\{f[s]+1\}$,其中$line[i][j]$表示i、j兩點確定的拋物線經過的所有的點,i是s中還未擊中的最小的點
復雜度是$O(n2^n)$
1#include<bits/stdc++.h> 2 #define pa pair<int,int> 3 #define lowb(x) ((x)&(-(x))) 4 #define REP(i,n0,n) for(i=n0;i<=n;i++) 5 #define PER(i,n0,n) for(i=n;i>=n0;i--) 6 #define MAX(a,b) ((a>b)?a:b) 7 #define MIN(a,b) ((a<b)?a:b) 8 #define CLR(a,x) memset(a,x,sizeof(a)) 9#define rei register int 10 using namespace std; 11 typedef long long ll; 12 const int maxn=20,maxs=1000000; 13 14 inline ll rd(){ 15 ll x=0;char c=getchar();int neg=1; 16 while(c<‘0‘||c>‘9‘){if(c==‘-‘) neg=-1;c=getchar();} 17 while(c>=‘0‘&&c<=‘9‘) x=x*10+c-‘0‘,c=getchar();18 return x*neg; 19 } 20 21 int N; 22 double pos[maxn][2]; 23 int line[maxn][maxn]; 24 int f[maxs],bin[maxn]; 25 26 inline bool eq(double a,double b){return fabs(a-b)<=1e-8;} 27 inline void getab(double &a,double &b,double x1,double y1,double x2,double y2){ 28 a=(x2*y1-x1*y2)/(x1*x2*(x1-x2)); 29 b=(x1*x1*y2-x2*x2*y1)/(x1*x2*(x1-x2)); 30 } 31 32 int main(){ 33 // freopen("testdata.in","r",stdin); 34 int i,j,k; 35 for(i=1,j=1;i<=19;i++,j<<=1) bin[i]=j; 36 for(int T=rd();T;T--){ 37 N=rd();rd(); 38 for(i=1;i<=N;i++) scanf("%lf%lf",&pos[i][0],&pos[i][1]); 39 for(i=1;i<=N;i++){ 40 for(j=i+1;j<=N;j++){ 41 double a,b;getab(a,b,pos[i][0],pos[i][1],pos[j][0],pos[j][1]); 42 43 int s=0; 44 if(a<0){ 45 for(k=1;k<=N;k++ ){ 46 if(eq(a*pos[k][0]*pos[k][0]+b*pos[k][0],pos[k][1])){ 47 s|=bin[k]; 48 } 49 } 50 } 51 line[i][j]=s; 52 // cout<<a<<" "<<b<<" "<<i<<" "<<j<<" "<<bitset<20>(s)<<endl; 53 }line[i][i]=bin[i]; 54 } 55 memset(f,127,sizeof(f)); 56 f[0]=0; 57 for(i=0;i<bin[N+1]-1;i++){ 58 for(j=1;bin[j]&i;j++); 59 for(k=j;k<=N;k++){ 60 if(bin[k]&i) continue; 61 f[i|line[j][k]]=min(f[i|line[j][k]],f[i]+1); 62 } 63 }printf("%d\n",f[bin[N+1]-1]); 64 } 65 66 return 0; 67 }
luogu2831 [NOIp2016]憤怒的小鳥 (狀壓dp)