zoukankan      html  css  js  c++  java
  • P2831 愤怒的小鸟

    传送门

    看到数据范围就知道是搜索或状压DP

    算了一波复杂度搜索好像过不了极限数据

    搞状压

    设 f [ i ] 表示所有猪的状态为 i (二进制下1表示死了,0表示没死)时需要的最少发射次数

    设 p [ i ] [ j ] 存经过第 i 只猪和第 j 只猪的抛物线经过的猪的状态(可以$n^2$预处理出来,解方程都会吧..)

    找到第一个没死的猪 i ,然后枚举所有其他没死的猪 j ,进行转移:

    f [ i|p [ i ] [ j ] ] = min ( f [ i|p [ i ] [ j ] ],f [ i ] + 1 )

    不用 n^2 枚举所有两只猪的 p [ i ] [ j ] ,因为第一头猪现在不死以后也要死,所以没有任何区别

    当然还要考虑只经过一头猪的情况: f [ i|(1<<i-1) ] = min ( f[ i|(1<<i-1) ],f [ i ] +1 )

    注意抛物线解析式中 a<0,记得判一下合法性

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    using namespace std;
    typedef long long ll;
    inline int read()
    {
        int x=0,f=1; char ch=getchar();
        while(ch<'0'||ch>'9') { if(ch=='-') f=-1; ch=getchar(); }
        while(ch>='0'&&ch<='9') { x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); }
        return x*f;
    }
    const double eps=1e-8;
    const int N=300007;
    
    int n,m,T;
    struct data
    {
        double x,y;
    }d[27];
    double a,b;
    inline void slove(double x1,double y1,double x2,double y2)//解方程
    {
        double t=x2*x2/x1/x1;
        b=(y2-y1*t)/(x2-x1*t); a=(y1-x1*b)/x1/x1;
    }
    int p[27][27];
    int f[N];
    void pre()
    {
        memset(p,0,sizeof(p));
        memset(f,0x3f,sizeof(f)); f[0]=0;//记得初始化
        for(int i=1;i<=n;i++)
            for(int j=i+1;j<=n;j++)
            {
                if(fabs(d[i].x-d[j].x)<eps) continue;//如果横坐标相同则无解
                slove(d[i].x,d[i].y,d[j].x,d[j].y);
                if(a>=0) continue;//判断合法性
                for(int k=1;k<=n;k++) if(fabs(a*d[k].x*d[k].x+b*d[k].x-d[k].y)<=eps)/*如果抛物线经过猪k就记录一下*/ p[i][j]|=(1<<k-1);
            }
    }
    int main()
    {
        T=read();
        while(T--)
        {
            n=read(); m=read();
            for(int i=1;i<=n;i++) scanf("%lf%lf",&d[i].x,&d[i].y);
            pre(); int mx=(1<<n)-1,pos;
            for(int i=0;i<=mx;i++)
            {
                for(int j=0;j<n;j++) if( !((i>>j)&1) ) { pos=j; break; }//找到第一只没死的猪
                f[i|(1<<pos)]=min(f[i|(1<<pos)],f[i]+1);//单独考虑
                for(int j=pos+1;j<n;j++)//与其他猪一起考虑
                    if( !((i>>j)&1) ) f[i|p[pos+1][j+1]]=min(f[i|p[pos+1][j+1]],f[i]+1);//注意p的下标
            }
            printf("%d
    ",f[mx]);
        }
        return 0;
    }

     

  • 相关阅读:
    IIS Express中添加MIME
    js立即执行函数IIFE(Immediatelyinvokedfunctionexpression)的几种写法
    笑话一则
    字符串操作类 NET代码积累之一
    UrlRewriter使用详解
    压缩和解压缩的方法 from Byte[]
    C#日期格式化
    JavaScript模拟进度条
    让visual studio 2005 自动为类加版权
    godaddy免费空间完美安装部署dedecms
  • 原文地址:https://www.cnblogs.com/LLTYYC/p/9824696.html
Copyright © 2011-2022 走看看