欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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]);
    }
}
相关标签: 状态压缩