1. 程式人生 > >[noip2016]憤怒的小鳥 題解

[noip2016]憤怒的小鳥 題解

n好小啊,當時十分年輕地寫了搜尋,自己的資料跑得賊快,但是最終測評只有60+呀,不過,這資料範圍,不應該一眼看出狀壓dp嗎,而且還十分簡單233。

考慮每一條拋物線,最多隻能有n^2級的數量,還是很小的,可以承受,然後就是狀態轉移了,每條拋物線都可以轉移一次。

大概的複雜度是O(n^2*2^n),還是軸對稱的233。

 #include<bits/stdc++.h>
using namespace std;
int T,m,n,tot,gun[500];
int f[262900];
double x[20],y[20],a,b;
bool kill(int id,double a,double
b) { double val=a*x[id]*x[id]+b*x[id]-y[id]; val=fabs(val); if(val<0.000001)return true;return false; } int main() { freopen("in.txt","r",stdin); scanf("%d",&T); while(T--) { scanf("%d%d",&n,&m);tot=0; for(int i=1;i<=n;i++)scanf("%lf%lf",&x[i],&y[i]); memset
(gun,0,sizeof(gun)); for(int i=1;i<=n;i++) for(int j=i+1;j<=n;j++) { if(x[i]==x[j])continue; a=(y[i]*x[j]-y[j]*x[i])/(x[i]*x[j]*(x[i]-x[j])); b=(y[i]-a*x[i]*x[i])/x[i]; if(a>=0.0)continue; tot++; for
(int k=1;k<=n;k++)if(kill(k,a,b))gun[tot]|=(1<<(k-1)); } for(int i=1;i<=n;i++)gun[++tot]|=(1<<(i-1)); sort(gun+1,gun+tot+1); tot=unique(gun+1,gun+tot+1)-gun-1; for(int i=1;i<=(1<<n);i++)f[i]=100000;f[0]=0; for(int i=0;i<(1<<n);i++) for(int j=1;j<=tot;j++) f[i|gun[j]]=min(f[i]+1,f[i|gun[j]]); cout<<f[(1<<n)-1]<<endl; } return 0; }