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

    题目描述

    Kiana 最近沉迷于一款神奇的游戏无法自拔。

    简单来说,这款游戏是在一个平面上进行的。

    有一架弹弓位于 (0,0)(0,0) 处,每次 Kiana 可以用它向第一象限发射一只红色的小鸟,小鸟们的飞行轨迹均为形如 y=ax^2+bxy=ax2+bx 的曲线,其中 a,ba,b 是Kiana 指定的参数,且必须满足 a < 0a<0,a,ba,b 都是实数。

    当小鸟落回地面(即 xx 轴)时,它就会瞬间消失。

    在游戏的某个关卡里,平面的第一象限中有 nn 只绿色的小猪,其中第 ii 只小猪所在的坐标为 left(x_i,y_i ight)(xi,yi)。

    如果某只小鸟的飞行轨迹经过了 left( x_i, y_i ight)(xi,yi),那么第 ii 只小猪就会被消灭掉,同时小鸟将会沿着原先的轨迹继续飞行;

    如果一只小鸟的飞行轨迹没有经过 left( x_i, y_i ight)(xi,yi),那么这只小鸟飞行的全过程就不会对第 ii 只小猪产生任何影响。

    例如,若两只小猪分别位于 (1,3)(1,3) 和 (3,3)(3,3),Kiana 可以选择发射一只飞行轨迹为 y=-x^2+4xy=x2+4x 的小鸟,这样两只小猪就会被这只小鸟一起消灭。

    而这个游戏的目的,就是通过发射小鸟消灭所有的小猪。

    这款神奇游戏的每个关卡对 Kiana来说都很难,所以Kiana还输入了一些神秘的指令,使得自己能更轻松地完成这个游戏。这些指令将在【输入格式】中详述。

    假设这款游戏一共有 TT 个关卡,现在 Kiana想知道,对于每一个关卡,至少需要发射多少只小鸟才能消灭所有的小猪。由于她不会算,所以希望由你告诉她。

    输入输出格式

    输入格式: 

    第一行包含一个正整数 T,表示游戏的关卡总数。

    下面依次输入这 T 个关卡的信息。每个关卡第一行包含两个非负整数 n,m n,m,分别表示该关卡中的小猪数量和 Kiana 输入的神秘指令类型。接下来的 n行中,第 i行包含两个正实数 xi,yi,表示第 i 只小猪坐标为 (xi,yi)。数据保证同一个关卡中不存在两只坐标完全相同的小猪。

    如果 m=0,表示Kiana输入了一个没有任何作用的指令。

    如果 m=1,则这个关卡将会满足:至多用 n/3+1⌉ 只小鸟即可消灭所有小猪。

    如果 m=2,则这个关卡将会满足:一定存在一种最优解,其中有一只小鸟消灭了至少 n/3⌋ 只小猪。

    保证 1n18,0m2,0<xi,yi<10,输入中的实数均保留到小数点后两位。

    上文中,符号c⌉ 和 c⌋ 分别表示对 c 向上取整和向下取整,例如:lceil 2.1 ceil = lceil 2.9 ceil = lceil 3.0 ceil = lfloor 3.0 floor = lfloor 3.1 floor = lfloor 3.9 floor = 32.1=2.9=3.0=3.0=3.1=3.9=3。

    输出格式:

    对每个关卡依次输出一行答案。

    输出的每一行包含一个正整数,表示相应的关卡中,消灭所有小猪最少需要的小鸟数量。

    输入输出样例

    输入样例#1: 
    2
    2 0
    1.00 3.00
    3.00 3.00
    5 2
    1.00 5.00
    2.00 8.00
    3.00 9.00
    4.00 8.00
    5.00 5.00
    输出样例#1:
    1
    1
    输入样例#2:
    3
    2 0
    1.41 2.00
    1.73 3.00
    3 0
    1.11 1.41
    2.34 1.79
    2.98 1.49
    5 0
    2.72 2.72
    2.72 3.14
    3.14 2.72
    3.14 3.14
    5.00 5.00
    输出样例#2:
    2
    2
    3
    
    输入样例#3: 
    1
    10 0
    7.16 6.28
    2.02 0.38
    8.33 7.78
    7.68 2.09
    7.46 7.86
    5.77 7.44
    8.24 6.72
    4.42 5.11
    5.42 7.79
    8.15 4.99
    输出样例#3:
    6
    

    说明

    【样例解释1】

    这组数据中一共有两个关卡。

    第一个关卡与【问题描述】中的情形相同,22只小猪分别位于(1.00,3.00)(1.00,3.00)和 (3.00,3.00)(3.00,3.00),只需发射一只飞行轨迹为y = -x^2 + 4xy=x2+4x的小鸟即可消灭它们。

    第二个关卡中有55只小猪,但经过观察我们可以发现它们的坐标都在抛物线 y = -x^2 + 6xy=x2+6x上,故Kiana只需要发射一只小鸟即可消灭所有小猪。

    【数据范围】

    ------------------------------------------------------------------

    听说这道题要用状压.....但基于现在我能避开DP就尽量避开Dp的策略 我选择爆搜一波(悄悄撒花

    其实搜并没有什么思维难度 甚至用不上题目给的m的信息

    对于每只猪了,存在两种情况:

    1.和之前的某猪连成线 我们可以暴力枚举 算出抛物线的系数 用na[i]和nb[i]记录

    2.不和之前的某猪连成线 那么就加入单独成线的行列之中 用 dx[i]和dy[i]记录

    每次dfs传入三个信息(now,u,v)// now当前猪 u被安排过了 v各自成一条线

    P.S. :当时以为 找之前的猪 和 从单个猪的行列中取出一只猪 暴力会GG 结果居然就这么水过去了????

    MARK:

    1.请注意哪些数组需要开为double

    2.判断两个浮点数相同的方式:做差之后小于某精度

    double eps=1e-8;

    bool cmp(double a,double b)

    {

      return( fabs(a-b)<eps );

    }

    3.ans的剪枝和更新条件、方式

    以下代码

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 #include<cmath>
     6 #define N 50
     7 using namespace std;
     8 struct node
     9 {
    10     double x,y;
    11 }e[N];
    12 int n,m,ans;
    13 double na[N],nb[N];
    14 double dx[N],dy[N];
    15 double eps=1e-8;
    16 bool cmp(double a,double b)
    17 {
    18     return( fabs(a-b)<eps );
    19 }
    20 void dfs(int now,int u,int v)//now当前猪 u被安排 v各自一条线 
    21 {
    22     if(u+v>=ans) return;
    23     if(now>n)
    24     {
    25         ans=u+v;
    26         return;
    27     }
    28     bool flag=0;
    29     for(int i=1;i<=u;i++)
    30         if( cmp(e[now].x*e[now].x*na[i]+e[now].x*nb[i],e[now].y) )//之前在线上
    31         {
    32             dfs(now+1,u,v);
    33             flag=1;
    34             break;
    35         }
    36     if(!flag)
    37     {
    38         for(int i=1;i<=v;i++)//选择和之前的猪连成一线 
    39         {
    40             if( cmp(e[now].x,dx[i]) ) continue;
    41             double a=(dx[i]*e[now].y-e[now].x*dy[i])/(e[now].x*e[now].x*dx[i]-e[now].x*dx[i]*dx[i]); 
    42             double b=(e[now].y-a*e[now].x*e[now].x)/(e[now].x);
    43             if(a<0)
    44             {
    45                 na[u+1]=a; nb[u+1]=b;//记下这条线 
    46                 double piu=dx[i],biu=dy[i]; 
    47                 for(int j=i;j<=v;j++)//暴力哭了的减单
    48                 {
    49                      dx[j]=dx[j+1];
    50                      dy[j]=dy[j+1];
    51                 }
    52                 dfs(now+1,u+1,v-1);
    53                 for(int j=v;j>=i;j--)//暴力哭了的加单
    54                 {
    55                      dx[j]=dx[j-1];
    56                      dy[j]=dy[j-1];
    57                 }
    58                 dx[i]=piu; dy[i]=biu;
    59             }
    60         }
    61         //选择不和现在的猪构成一个新线 
    62         dx[v+1]=e[now].x;
    63         dy[v+1]=e[now].y; 
    64         dfs(now+1,u,v+1);
    65     }
    66 }
    67 int main()
    68 {
    69     int t;
    70     scanf("%d",&t);
    71     while(t--)
    72     {
    73         scanf("%d%d",&n,&m);
    74         for(int i=1;i<=n;i++)
    75             scanf("%lf%lf",&e[i].x,&e[i].y);
    76         ans=1000;
    77         dfs(1,0,0);
    78         printf("%d
    ",ans);
    79     }
    80     return 0;
    81 }
    82 /*
    83 1
    84 5 2
    85 1.00 5.00
    86 2.00 8.00
    87 3.00 9.00
    88 4.00 8.00
    89 5.00 5.00
    90 */
  • 相关阅读:
    antd vue 刷新保留当前页面路由,保留选中菜单,保留menu选中
    你不知道的arguments
    js触发复制、粘贴,设置和读取剪切板的数据
    vue父组件data改变触发子组件prop值变化
    关于英语的unless
    PHP闭包调用外部参数使用范例
    全国省市区数据库数据,以及可视化echarts相关geoJson数据
    PHP开发环境搭建&mdash;phpstudy+eclipse+php development tool+xdebug+composer
    LBS——实现附近功能的几种方案浅谈
    好文共赏
  • 原文地址:https://www.cnblogs.com/kylara/p/9748734.html
Copyright © 2011-2022 走看看