愤怒的小鸟——去年的题今年才做完

  先预处理每两只猪构成的抛物线可以打到的猪。然后枚举当前状态是多打一头猪还是多打一条抛物线。开始因为把手写abs 写成了return x>0?x:-1; 而无法正常预处理,盯着代码看了一个早上,实际上问题根本不在后面计算部分。

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
const int N=20,INF=0x3f3f3f3f;
const double DIF=1e-8;
int n,m,FULL,f[(1<<N)],bird[N][N];
double x[N],y[N];

bool equal(double x,double y){return abs(x-y)<=DIF;}

int main(){
    int T;cin>>T;
    while(T--){
        memset(x,0,sizeof x);memset(y,0,sizeof y);memset(f,0x3f,sizeof f);
        memset(bird,0,sizeof bird);
        
        cin>>n>>m;
        FULL=(1<<n)-1;
        for(int i=1;i<=n;i++)cin>>x[i]>>y[i];
        
        for(int i=1;i<n;i++)
            for(int j=i+1;j<=n;j++)
                if(!equal(x[i],x[j])){
                    double a=(y[i]/x[i]-y[j]/x[j])/(x[i]-x[j]);
                    if(a>=0)continue;
                    double b=y[i]/x[i]-a*x[i];
                    for(int k=1;k<=n;k++)
                        if(equal(a*x[k]+b,y[k]/x[k]))
                            bird[i][j]=bird[i][j]|(1<<(k-1));
                }
        
        
        f[0]=0;
        for(int k=0;k<=FULL;k++)
            for(int i=1;i<=n;i++)
                if(!(k&(1<<(i-1)))){
                    for(int j=i;j<=n;j++)
                        if(i==j)
                            f[k|(1<<(j-1))]=min(f[k|(1<<(j-1))],f[k]+1);
                        else if(!equal(x[i],x[j]))
                            f[k|bird[i][j]]=min(f[k|bird[i][j]],f[k]+1);
                    break;
                }
        
        cout<<f[FULL]<<endl;
    }
    return 0;
}
Method_01

  Vijos 691ms

posted @ 2017-10-26 07:48  Darkins  阅读(125)  评论(0)    收藏  举报