zoukankan      html  css  js  c++  java
  • 洛谷P2831 愤怒的小鸟——贪心?状压DP

    题目:https://www.luogu.org/problemnew/show/P2831

    一开始想 n^3 贪心来着;

    先按 x 排个序,那么第一个不就一定要打了么?

    在枚举后面某一个,和它形成一条抛物线,选能顺便打掉最多的那个;

    然后连样例都过不了...

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #define eps 1e-9
    using namespace std;
    int T,n,m,ans;
    bool vis[20];
    struct N{
        double x,y;
    }p[20];
    bool cmp(N x,N y){return x.x<y.x;}
    int main()
    {
        scanf("%d",&T);
        while(T--)
        {
            memset(vis,0,sizeof vis);
            ans=0;
            scanf("%d%d",&n,&m);
            for(int i=1;i<=n;i++)
                scanf("%lf%lf",&p[i].x,&p[i].y);
            sort(p+1,p+n+1,cmp);
            for(int i=1;i<=n;i++)
            {
                if(vis[i])continue; vis[i]=1;
    //            printf("i=%d
    ",i);
                double x1=p[i].x, y1=p[i].y, xx=x1*x1, x2,y2,xy,a,b,aa=0,bb=0;
                for(int j=i+1;j<=n;j++)
                {
                    int cnt=1,mx=0;
                    if(vis[j]||p[j].x==p[i].x)continue;
                    x2=p[j].x; y2=p[j].y; xy=x2*x2;
    //                y2=y2/x2*x1; xy=xy/x2*x1;
    //                a=(y1-y2)/(xx-xy); 
                    a=(y1*x2-y2*x1)/(x1*x2*(x1-x2));
                    b=(y1-a*xx)/x1;
    //                printf("%lf %lf
    ",a,b);
                    for(int k=j+1;k<=n;k++)
                    {
                        if(vis[k])continue;
                        double tx=p[k].x,ty=p[k].y;
                        if(a*tx*tx+b*tx-ty<eps)cnt++;
                    }
                    if(cnt>mx)mx=cnt,aa=a,bb=b;
                }
                if(aa||bb)
                    for(int j=i+1;j<=n;j++)
                        if(fabs(aa*p[j].x*p[j].x+bb*p[j].x-p[j].y)<eps)vis[j]=1;
                ans++;
            }
            printf("%d
    ",ans);
        }
        return 0;
    }

    仔细想想,贪心可能是错的;

    正解是状压DP,DP真是与贪心相对的正确解法啊...

    n 很小,所以想到状压,记录所有可能的抛物线的打猪情况;

    然后类似背包转移即可...

    代码如下:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #define eps 1e-8
    using namespace std;
    int T,n,m,f[262900],g[500],tot;
    double x[20],y[20];
    bool ck(int k,double a,double b)
    {
        return fabs(a*x[k]*x[k]+b*x[k]-y[k])<eps;
    }
    int main()
    {
        scanf("%d",&T);
        while(T--)
        {
            scanf("%d%d",&n,&m);
            for(int i=1;i<=n;i++)scanf("%lf%lf",&x[i],&y[i]);
            memset(g,0,sizeof g); double a,b;
            for(int i=1;i<=n;i++)
                for(int j=i+1;j<=n;j++)
                {
                    if(x[i]==x[j])continue;
                    a=(y[i]*x[j]-y[j]*x[i])/(x[i]*x[j]*(x[i]-x[j]));
                    b=(y[i]-a*x[i]*x[i])/x[i];
                    if(a>=0)continue;//>=而非> ! 
                    tot++;
                    for(int k=1;k<=n;k++)
                        if(ck(k,a,b))g[tot]|=(1<<(k-1));
                }
            for(int i=0;i<n;i++)g[++tot]|=(1<<i);
            sort(g+1,g+tot+1);
            tot=unique(g+1,g+tot+1)-g-1;
            memset(f,0x3f,sizeof f); f[0]=0;
            for(int i=0;i<(1<<n);i++)
                for(int j=1;j<=tot;j++)
                    f[i|g[j]]=min(f[i|g[j]],f[i]+1);
            printf("%d
    ",f[(1<<n)-1]);
        }
        return 0;
    }
  • 相关阅读:
    .net core 3.1 过滤器(Filter) 和中间件和AOP面向切面拦截器
    socket通信框架——boost asio
    远程过程调用框架——gRPC
    数据序列化工具——flatbuffer
    springboot项目启动----8080端口被占用排雷经过
    如何配置HOSTS文件
    使用线程Callable实现分段获取一个url连接的资源数据
    Socket网络编程课件
    (6)优化TCP编写 服务器端同时支持多个客户端同时访问
    SpringBoot配置属性之Security
  • 原文地址:https://www.cnblogs.com/Zinn/p/9211030.html
Copyright © 2011-2022 走看看