愤怒的小鸟

题解:

去年noip的时候写的暴力然后就有80分

正解比较显然

先枚举状态i 表示存在哪些猪,再枚举转移(由两个点确定最大能消灭多少)

另外一个套路就是先确定一个点

于是复杂度就是T*n*2^n了

两个点在一条直线上和a>0都要舍去

代码还是挺好写的

代码:

#include <bits/stdc++.h>
using namespace std;
#define rint register int
#define IL inline
#define rep(i,h,t) for (rint i=h;i<=t;i++)
#define dep(i,t,h) for (rint i=t;i>=h;i--)
#define me(x) memset(x,0,sizeof(x))
const int N=(1<<20)+10;
double eps=1e-8;
double a[20],b[20];
int f[N],n,m,ans[20][20];
const int INF=1e9;
IL int js(int x,int y)
{
    double ve1[3],ve2[3];
    ve1[1]=a[x],ve1[2]=a[y];
    ve2[1]=b[x],ve2[2]=b[y];
    double t=ve1[1]*ve1[2]-ve1[2]*ve1[2];
    if (abs(t)<eps) return(0);
    double x1=(ve2[1]/ve1[1]*ve1[2]-ve2[2])/t;
    double x2=(ve2[1]-ve1[1]*ve1[1]*x1)/ve1[1];
    if (x1>0) return(0);
    int ans=0;
    rep(i,1,n)
    {
      if (abs(x1*a[i]*a[i]+x2*a[i]-b[i])<eps) ans=ans|(1<<(i-1));
      int cnt=1;
      cnt++;
    }
    return(ans);
}
int main()
{
    freopen("1.in","r",stdin);
    freopen("1.out","w",stdout);
    ios::sync_with_stdio(false);
    int T;
    cin>>T;
    rep(kk,1,T)
    {
        cin>>n>>m;
        rep(i,1,n) cin>>a[i]>>b[i];
        me(f);
        rep(i,1,n)
        {
          rep(j,1,n)
            if (i!=j) ans[i][j]=js(i,j);
          ans[i][i]=(1<<(i-1));
        }
        rep(i,0,(1<<n)-1) f[i]=INF;
        f[0]=0;
        rep(i,0,(1<<n)-1)
        {
            if (f[i]!=INF)
            {
                int j;
                for (j=1;j<=n;j++) if (((i>>(j-1))&1)==0) break;
                rep(k,1,n)
                  f[i|ans[j][k]]=min(f[i|ans[j][k]],f[i]+1);
            }
        }
        cout<<f[(1<<n)-1]<<endl;
    }
    return 0;
}

 

posted @ 2018-10-01 15:57  尹吴潇  阅读(129)  评论(0编辑  收藏  举报