愤怒的小鸟(爆搜,剪枝)

题目描述

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想知道,对于每一个关卡,至少需要发射多少只小鸟才能消灭所有的小猪。由于她不会算,所以希望由你告诉她。

输入输出格式

输入格式:

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

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

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

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

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

保证 1leq n leq 181n18 , 0leq m leq 20m2 , 0 < x_i,y_i < 100<xi,yi<10 ,输入中的实数均保留到小数点后两位。

上文中,符号 lceil c ceilc⌉ 和 lfloor c floorc⌋ 分别表示对 cc 向上取整和向下取整,例如: 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 。

输出格式:

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

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

思路:

没什么好说的。。。只能%%一群状压大佬

我是这么想的,一个猪被打掉,要么是单独的一只小鸟干的

要么是被一只路过的小鸟干的

那么,在经过一个没有被打掉的猪的时候,将这个猪与其他没有打掉的猪尝试配对

算出一条抛物线,看这条路上能打掉几只猪,并打标记

当然,也可以不算抛物线,默认用一只鸟打掉

加一个最优化剪枝即可

(ps 注意精度)

代码:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#define rii register int i
#define rij register int j
#define inf 19260817
#define eps 0.0000001
using namespace std;
int n,m,t,ans;
struct pw{
    double a,b;
}pwx[20];
struct pig{
    double x,y;
}zb[20];
double bjx[20],bjy[20];
inline pw echs(int wz,int i)
{
    pw an;
    double lzn=zb[wz].x;
    double rxz=zb[wz].y;
    double ltt=(rxz*bjx[i]-bjy[i]*lzn);
    ltt/=(lzn*lzn*bjx[i]-bjx[i]*bjx[i]*lzn);
    double kkk=(rxz-lzn*lzn*ltt)/lzn;
    an.a=ltt;
    an.b=kkk;
    return an;
}
void dfs(int wz,int sl,int sy)
{
    if(sl+sy>=ans)
    {
        return;
    }
    if(wz>=n+1)
    {
        ans=sl+sy;
        return;
    }
    int pd=0;
    for(rii=1;i<=sl;i++)
    {
        if(fabs(pwx[i].a*zb[wz].x*zb[wz].x+pwx[i].b*zb[wz].x-zb[wz].y)<=eps)
        {
            dfs(wz+1,sl,sy);
            pd=1;
            break;
        }
    }
    if(pd!=1)
    {
        for(rii=1;i<=sy;i++)
        {
            if(fabs(zb[wz].x-bjx[i])<eps)
            {
                continue;
            }
            pw kk=echs(wz,i);
            if(kk.a<0)
            {   
                pwx[sl+1]=kk;
                double ltt=bjx[i];
                double kkk=bjy[i];
                for(rij=i;j<sy;j++)
                {
                    bjx[j]=bjx[j+1];
                    bjy[j]=bjy[j+1];
                }
                dfs(wz+1,sl+1,sy-1);
                for(rij=sy;j>i;j--) 
                {
                    bjx[j]=bjx[j-1];
                    bjy[j]=bjy[j-1];
                }
                bjx[i]=ltt;
                bjy[i]=kkk;
            }
        }
        bjx[sy+1]=zb[wz].x;
        bjy[sy+1]=zb[wz].y;
        dfs(wz+1,sl,sy+1);
    }
}
int main()
{
    scanf("%d",&t);
    for(rii=1;i<=t;i++)
    {
        scanf("%d%d",&n,&m);
        for(rij=1;j<=n;j++)
        {
            scanf("%lf%lf",&zb[j].x,&zb[j].y);
        }
        ans=inf;
        dfs(1,0,0);
        printf("%d
",ans); 
    } 
}
原文地址:https://www.cnblogs.com/ztz11/p/9401434.html