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

    可怕的题目

    直接上代码了

    #include<cstring>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<iostream>
    #define eps (1e-6)
    #define re register
    #define min(a,b) ((a) < (b) ? (a) : (b))
    using namespace std;
    double x[21],y[21];
    double a,b;
    int d[21][21];
    int T,n,m;
    int f[262150],dp[262150];
    int ans;
    inline int check(int i,int j)
    {
        double t1=x[i]*x[i];
        double t2=x[j]*x[j];
        b=(t2*y[i]-y[j]*t1)/(x[i]*t2-x[j]*t1);
        a=(y[i]*x[j]-y[j]*x[i])/(t1*x[j]-t2*x[i]);
        if(a>-eps) return 0;
        return 1;
    }
    inline int pd(int k)
    {
        double yy=a*x[k]*x[k]+x[k]*b;
        if(yy+eps>y[k]&&yy-eps<y[k]) return 1;
        return 0;
    }
    inline void dfs (int k,int step)//k为当前的状态,step为所用的抛物线条数
    {
        if(dp[k]<=step) return;//如果当前到达这个状态再次之前有更优的解或相同的解,那么就不用往下搜了
        dp[k]=step;//记忆化dp[k]表示到k这个状态的最小抛物线数量
        if(step>=ans) return;
        if(k==(1<<n)-1)//到达终点
        {
            ans=min(ans,step);
            dp[k]=ans;
            return;
        }
        //我们额外枚举一条抛物线
        //我们枚举的这条抛物线必须能打到一只当前没有打到的猪
        //于是我们像树状数组里的lowbit操作一样,取出最靠后的那一只被打到的猪从它引出抛物线就行了
        //这是为什么呢,为什么在这一层搜索里没有必要将所有的抛物线都尝试一遍呢
        //其实很简单,因为就算这一层枚举出所有抛物线的情况,下一层也会枚举到的,于是就没有什么必要全部去枚举了
        int xx=((1<<n)-1)^k;
        xx=log2(xx&(-xx))+1;
        for (int j=1;j<=n;++j)
            dfs(k|d[xx][j],step+1);
    }
    int main()
    {
        scanf("%d",&T);
        while(T--)
        {
            memset(dp,20,sizeof(dp));
            memset(d,0,sizeof(d));
            scanf("%d%d",&n,&m);
            for(re int i=1;i<=n;i++)
                scanf("%lf%lf",&x[i],&y[i]);
            for(re int i=1;i<=n;i++)
            	d[i][i]=1<<(i-1);
            for(re int i=1;i<=n;i++)
            for(re int j=i+1;j<=n;j++)//枚举两只猪之后,再枚举其他猪看看这条抛物线是否能打到其他猪
            {
                int now=0;
                if(x[i]<x[j]+eps&&x[i]>x[j]-eps) continue;
                if(!check(i,j)) continue;
                now|=1<<(i-1);
                now|=1<<(j-1);
                for(re int k=1;k<=n;k++)
                if(k!=i&&k!=j&&pd(k)) now|=1<<(k-1);
                d[i][j]=d[j][i]=now;//d[i][j]表示i和j点之间的抛物线可以打到的猪的状态是什么
            }
            ans=9999;
            dfs(0,0);
            printf("%d
    ",ans);
        }
    }
    
  • 相关阅读:
    Windows Azure Cloud Service (14) 使用Windows Azure诊断收集日志记录数据
    Windows Azure Cloud Service (13) 用Visual Studio 2010 将应用程序部署到Windows Azure平台
    Windows Azure Cloud Service (15) 多个VM Instance场景下如何处理ASP.NET Session
    Windows Azure Storage (5) Windows Azure Drive
    Windows Azure Storage (7) 使用工具管理Windows Azure Storage
    SQL Azure(二) SQL Azure vs SQL Server
    webbrowser的自动提交
    提取视频的背景声音的软件
    Listview列排序的bug原因
    两个奇怪的问题
  • 原文地址:https://www.cnblogs.com/asuldb/p/10207813.html
Copyright © 2011-2022 走看看