LUOGU P2831 愤怒的小鸟 (NOIP 2016)
程序员文章站
2024-03-23 22:54:16
...
题解
好像昨天wxl大爷讲的是O(Tn*2^n)的做法,后来没想通,就自己写了个O(Tn^2*2^n)的暴力状压,
莫名其妙过了??数量级二十亿??懵逼,可能到了CCF老爷机上就T了。dp[S]表示现在猪的状态,
然后枚举两只鸟,然后开炮。
代码
#include<bits/stdc++.h>
using namespace std;
const int MAXN = 18;
const int inf = 0x3f3f3f3f;
const double eps = 1e-6; //精度
struct PIG{
double x,y;
}p[20];
int cnt;
int n,m,T,S,pre;
int dp[1<<MAXN];
double a,b;
int main(){
scanf("%d",&T);
while(T--){
memset(dp,0x3f,sizeof(dp));
dp[0]=0;
scanf("%d%d",&n,&m);
for(register int i=1;i<=n;i++)
scanf("%lf%lf",&p[i].x,&p[i].y);
for(register int i=0;i<((1<<n)-1);i++){
S=0;a=0;b=0;pre=0;
if(dp[i]==inf) continue;
for(register int j=1;j<=n;j++){
S=0;pre=0;a=0;b=0;
if((i&(1<<(j-1)))==0){
S|=(1<<(j-1));
pre=j;
}
if(!pre) continue;
for(register int k=1;k<=n;k++)
if((i&(1<<(k-1)))==0 && k!=j)
if(p[pre].x!=p[k].x){
a=p[pre].y*p[k].x/p[pre].x-p[k].y; //二次函数表达式,很好推
a/=(p[pre].x*p[k].x-p[k].x*p[k].x);
if(a>=0) continue;
else{
b=(p[pre].y-a*p[pre].x*p[pre].x)/p[pre].x;
break;
}
}
if(a<0)
for(register int j=1;j<=n;j++) //看是否能打到更多的鸟
if(fabs(a*p[j].x*p[j].x+b*p[j].x-p[j].y)<=eps && j!=pre)
S|=(1<<(j-1));
dp[S|i]=min(dp[S|i],dp[i]+1);
}
}
printf("%d\n",dp[(1<<n)-1]);
}
}