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

    题目

    Description

    https://www.luogu.org/problem/show?pid=2831
    Kiana最近沉迷于一款神奇的游戏无法自拔。
    简单来说,这款游戏是在一个平面上进行的。
    有一架弹弓位于(0,0)处,每次Kiana可以用它向第一象限发射一只红色的小鸟,小鸟们的飞行轨迹均为形如y = ax^2 + bx的曲线,其中a, b是Kiana指定的参数,且必须满足a<0。
    当小鸟落回地面(即x轴)时,它就会瞬间消失。
    在游戏的某个关卡里,平面的第一象限中有n只绿色的小猪,其中第i只小猪所在的坐标为(xi,yi)。
    如果某只小鸟的飞行轨迹经过了(xi,yi),那么第i只小猪就会被消灭掉,同时小鸟将会沿着原先的轨迹继续飞行;
    如果一只小鸟的飞行轨迹没有经过(xi,yi),那么这只小鸟飞行的全过程就不会对第i只小猪产生任何影响。
    例如,若两只小猪分别位于(1, 3 )和(3, 3 )
    Kiana可以选择发射一只飞行轨迹为y=-x^2+ 4x的小鸟,这样两只小猪就会被这只小鸟一起消灭。
    而这个游戏的目的,就是通过发射小鸟消灭所有的小猪。
    这款神奇游戏的每个关卡对Kiana来说都很难,所以Kiana还输入了一些神秘的指令,使得自己能更轻松地完成这个游戏。这些指令将在【输入格式】中详述。
    假设这款游戏一共有T个关卡,现在Kiana想知道,对于每一个关卡,至少需要发射多少只小鸟才能消灭所有的小猪。由于她不会算,所以希望由你告诉她。

    Input

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

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

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

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

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

    保证1<=n<=18,0<=m<=2,0< xi,yi<10,输入中的实数均保留到小数点后两位。

    上文中,符号和分别表示对c向上取整和向下取整

    Output

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

    题解

    题目没有贴全,样例也没有打了(到Luogu上去看)
    这道题目。。。。怎么说。。。。其实有点水。
    作为Tg的D2T3确实偏简单了一些(T2有毒)






    我的思路比较暴力:每次强行枚举任意两只猪,算出其抛物线(判断是否合法),计算出最多能够消灭几只猪(使用状压存状态)。最后再添加一个单独消灭某只猪的DFS。强暴DFS计算。


    至于优化,我加了一个记忆化搜索和对ans的剪枝。
    这题的思路十分暴力,我在CJOJ上很快就AC了


    这里写图片描述




    不知道再别的OJ上是不是AC的(没有试,很可能被卡精度)
    希望诸位dalao帮我测一测
    如果Wa了,也请各位dalao帮我查一下错误,谢谢了

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    const int MAX=25;
    double A,B;
    int ans;
    int n,m,T;
    int f[MAX][(1<<20)];//记忆化
    inline void solve(int i,int j);//求解抛物线
    struct Pig
    {
    	double x,y;
    }P[MAX];
    bool operator <(Pig a,Pig b)
    {
    	if(a.x!=b.x)
    		return a.x<b.x;
        else
    		return a.y<b.y;
    }
    inline void DFS(int x,int t,int b)//还有x只猪没被消灭,t用来存储消灭情况
    {
    	if(x<=1)//只有一直猪也只接判断
    	{
    		ans=min(ans,b+x);//b用来储存鸟的数量
    		return;
    	}
    	if(b>=ans-1)return;
    	if(f[x][t]!=0)
    	{
    		if(b>=f[x][t])return;
    		else
    			f[x][t]=b;
    	}
    	else
    	   f[x][t]=b;
    	for(int i=1;i<=n;++i)
    	{
    		int tt=t,kk=0;
    		if((1<<(i-1))&t)//这只猪已经死了
    			continue;
    		for(int j=i+1;j<=n;++j)
    		{
    			if((1<<(j-1))&t)//这只猪也死了
    				continue;
    			tt= t|(1<<(i-1));
    			tt=tt|(1<<(j-1));
    			kk=2;
    			solve(i,j);//求解这两只猪所在的抛物线
    			if(A>=-0.001||B<=0.001)continue;//不合题意的抛物线
    			for(int k=1;k<=n;++k)//检查是否有猪在这条抛物线上
    			{
    				if(!(tt&(1<<(k-1))))//猪没有死才检查
    				{
    					double yy=P[k].x*(A*P[k].x+B);
    					if(fabs(yy-P[k].y)<=0.0001)//如果能够打死(卡下精度)
    					{
    						 kk+=1;
    						 tt=tt|(1<<(k-1));
    					}
    					//	if(yy<=0)//这只鸟已经没了
    				    //		break;
    				}
    			}
    			DFS(x-kk,tt,b+1);
    		}
    		DFS(x-1,t|(1<<(i-1)),b+1);//单独弄死
    	}
    	
    		
    }
    int main()
    {
    	cin>>T;
    	while(T--)
    	{
    		memset(f,0,sizeof(f));
    		cin>>n>>m;
    		if(m==0)ans=n;
    		if(m==1)ans=n/3+1;
    		if(m==2)ans=1+(n-n/3);
    		for(int i=1;i<=n;++i)
    			cin>>P[i].x>>P[i].y;
    	    DFS(n,0,0);
    		cout<<ans<<endl;
    	}
    }
    inline void solve(int i,int j)
    {
    	double a1=P[i].x*P[i].x;
    	double a2=P[j].x*P[j].x;
    	double b1=P[i].x;
    	double b2=P[j].x;
    	double c1=P[i].y;
    	double c2=P[j].y;
    	double tt=a1/a2;
    	a2=a1;b2*=tt;c2*=tt;//把a的系数化成一样的
    	if(fabs(b2-b1)<=0.001)//不能够除以0
    	{
    		 B=-1000;
    		 A=+1000;
    		 return;
    	}
    	B=(c2-c1)/(b2-b1);//加减消元求B
    	if(fabs(a1)<=0.001)//不能够除以0
    	{
    		B=-1000;
    		A=+1000;
    		return;
    	}
    	A=(c1-B*b1)/a1;//代入消元求A
    }
    
  • 相关阅读:
    C# 导出 Excel 自定义输出格式
    ONE路由协议模块分析与应用
    2440(ARM9) L3G4200D ADXL345 裸机程序
    C# SerialPort.close() bug解决方法
    C++ Primer 第五章 表达式
    C++ Primer 第一章 快速入门
    C++ Primer 第二章 变量和基本类型
    虚拟机virtualbox中挂载新硬盘
    C++ Primer 第四章 数组与指针
    C++ Primer 第三章 标准库类型
  • 原文地址:https://www.cnblogs.com/cjyyb/p/7197160.html
Copyright © 2011-2022 走看看