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

    Link:

    P2831 传送门

    Solution:

    其实是一道裸爆搜都能过的题目……

    看到$nle 18$想到状压$dp$

    令$dp[i]$,表示达到当前状态的最小代价

    可以发现只要两个点就能确定一条从原点出发的抛物线

    因此每次对于一个特定的状态枚举两点确定抛物线转移就好了

    $O(n^3)$预处理出每两个点形成的抛物线能经过的状态$f[i][j]$,接下来$O(n^2*2^n)$转移

    但每次一定要$O(n^2)$枚举所有的点对吗?

    其实完全可以通过构造有序性来去掉一个$n$:

    默认从小到大打猪,每次都打最小未被打的,毕竟先打了后面的也要再回头打前面的

    这样就确定了点对中的第一个点:最小未被打的点

    只要枚举另一个点就将复杂度降到了$O(n*2^n)$

    Code:

    #include <bits/stdc++.h>
    
    using namespace std;
    const int MAXN=1<<18,INF=1<<27;
    const double eps=1e-6;
    double x[20],y[20];
    int T,n,m,dp[MAXN],f[20][20];
    
    int main()
    {
        scanf("%d",&T);
        while(T--)
        {
            scanf("%d%d",&n,&m);
            for(int i=0;i<n;i++)
                scanf("%lf%lf",&x[i],&y[i]);
            memset(f,0,sizeof(f));
            for(int i=0;i<n;i++)
                for(int j=0;j<n;j++)
                {
                    if(i==j){f[i][j]=(1<<i);continue;}
                    double a=(y[j]/x[j]-y[i]/x[i])/(x[j]-x[i]);
                    double b=y[i]/x[i]-a*x[i];
                    if(a>-eps) continue;
                    
                    for(int k=0;k<n;k++)
                        if(fabs(a*x[k]*x[k]+b*x[k]-y[k])<=eps)
                            f[i][j]|=(1<<k);
                }
            
            for(int i=0;i<MAXN;i++) dp[i]=INF;
            int fst;dp[0]=0;
            for(int i=0;i<(1<<n);i++)
            {
                if(dp[i]==INF) continue;
                for(fst=0;fst<n;fst++)
                    if(!(i&(1<<fst))) break;            
                for(int j=0;j<n;j++)
                    dp[i|f[fst][j]]=min(dp[i|f[fst][j]],dp[i]+1);
            }
            printf("%d
    ",dp[(1<<n)-1]);
        }
        return 0;
    }

    Review:

    学会利用构造有序性的方式减掉一维的枚举

  • 相关阅读:
    Hash详解
    手写2048
    20180429模拟赛T1——添边问题
    题解:UVA1025 A Spy in the Metro
    20180418模拟赛T2——Gym
    20180418模拟赛T1——Seq
    学习:中国剩余定理
    20180414模拟赛T2——拼图
    20180414模拟赛T1——BEAD
    学习:树状数组
  • 原文地址:https://www.cnblogs.com/newera/p/9303735.html
Copyright © 2011-2022 走看看