https://www.luogu.org/problem/show?pid=2831

BFS

看到N这么小就可以想到搜索,求最少步数显然应该用BFS。

在这题中过两猪可以唯一确定一条抛物线,每一步可以发射两只猪确定的一条抛物线(打下这条抛物线上的所有猪),也可以发射一条只经过一只猪的抛物线(只打下这只猪)。

这时可以想到状压存储每个状态,并且读入所有猪时预处理一下每两只猪确定的抛物线。

两点确定一条过原点的抛物线y=ax2+bx的方法:点(x1, y1) (x2, y2)过抛物线,得y1=ax12+bx1,y2=ax22+bx2,两式分别变形得y1/x1-ax1=y2/x2-ax2=b,再整理得a=(y2/x2-y1/x1)/(x2-x1)。求出a后往回代可求出b。

记得记录每个状态是否已经搜索过,避免重复的状态入队。由于共有2n个状态,故时间复杂度是O(2n)的。如果不剪枝就是O(n!)。

题目给的m应该是用来xjb剪枝用的,但是m=2怎么用我也不懂……

注意事项:

  • 判断两个浮点数相等要考虑精度误差。
  • stl的queue不开优化会很慢,可以考虑手写队列。
#include <algorithm>
#include <cstring>
#include <iostream>
#include <queue>
#include <vector>
#include <cmath>
using namespace std;
bool equal(double x, double y, double eps = 1e-)
{
return fabs(x - y) <= eps;
}
int n;
bool m[];
pair<double, double> pigs[];
unsigned target; // 搜索的最终目标,即第1~n位均为1
unsigned pwxs[][]; // pwxs[i][j] => i、j两只猪所在抛物线上的所有猪
bool visited[( << )];
int bfs()
{
typedef pair<unsigned, int> state; // <状态, 步数>
queue<state> q;
q.push(make_pair(, ));
while (!q.empty())
{
state x = q.front();
q.pop(); // 用一只鸟打一只猪的情况
for (int i = ; i <= n; i++)
{
if (!(x.first & ( << i))) // 如果i猪还没被打下
{
state y = x;
y.first |= ( << i);
y.second++;
if (y.first == target)
return y.second;
if (!visited[y.first] && !(m[] && y.second > (int)(n * 1.0 / + )))
{
q.push(y);
visited[y.first] = true;
}
}
} // 用一只鸟打两只猪的情况
for (int i = ; i <= n; i++)
{
for (int j = i + ; j <= n; j++)
{
if (!(x.first & ( << i)) && !(x.first & ( << j))) // 如果i、j猪都还没被打下
{
state y = x;
y.first |= pwxs[i][j];
y.second++;
if (y.first == target)
return y.second;
if (!visited[y.first] && !(m[] && y.second > (int)(n * 1.0 / + )))
{
q.push(y);
visited[y.first] = true;
}
}
}
}
}
return -;
}
int main()
{
ios::sync_with_stdio(false);
int t;
cin >> t;
while (t--)
{
memset(visited, false, << ); int c;
cin >> n >> c;
m[c] = true; for (int i = ; i <= n; i++)
for (int j = ; j <= n; j++)
pwxs[i][j] = ; target = ;
for (int i = ; i <= n; i++)
target |= ( << i); double a, b;
for (int i = ; i <= n; i++)
{
cin >> a >> b;
pigs[i] = make_pair(a, b);
} for (int i = ; i <= n; i++)
{
for (int j = i + ; j <= n; j++)
{
/* ∵ y1=ax1^2+bx1, y2=ax2^2+bx2
∴ b=y1/x1-ax1=y2/x2-ax2
∴ a=(y2/x2-y1/x1)/(x2-x1) */
double &x1 = pigs[i].first, &y1 = pigs[i].second;
double &x2 = pigs[j].first, &y2 = pigs[j].second;
a = (y2 / x2 - y1 / x1) / (x2 - x1);
b = y1 / x1 - a * x1;
if (a < )
{
for (int k = ; k <= n; k++)
{
double &x = pigs[k].first, &y = pigs[k].second;
if (equal(a * x * x + b * x, y))
pwxs[i][j] |= ( << k);
}
}
}
}
cout << bfs() << endl;
}
return ;
}

看到N这么小就可以想到搜索,求最少步数显然应该用BFS。

在这题中过两猪可以唯一确定一条抛物线,每一步可以发射两只猪确定的一条抛物线(打下这条抛物线上的所有猪),也可以发射一条只经过一只猪的抛物线(只打下这只猪)。

这时可以想到状压存储每个状态,并且读入所有猪时预处理一下每两只猪确定的抛物线。

记得记录每个状态是否已经搜索过,避免重复的状态入队。

【NOIP2016提高组】愤怒的小鸟的更多相关文章

  1. [NOIp2016提高组]愤怒的小鸟

    题目大意: 平面直角坐标系的第一象限有n(n<=18)个点,你可以每次给出一个形如y=ax^2+bx的函数把经过这条函数的点消掉,问消掉所有的点至少要多少函数? 思路: 枚举每两个点对,可以唯一 ...

  2. 【题解】NOIP2016提高组 复赛

    [题解]NOIP2016提高组 复赛 传送门: 玩具谜题 \(\text{[P1563]}\) 天天爱跑步 \(\text{[P1600]}\) 换教室 \(\text{[P1850]}\) 组合数问 ...

  3. 【题解】NOIP2016 提高组 简要题解

    [题解]NOIP2016 提高组 简要题解 玩具迷题(送分) 用异或实现 //@winlere #include<iostream> #include<cstdio> #inc ...

  4. NOIP2016提高组解题报告

    NOIP2016提高组解题报告 更正:NOIP day1 T2天天爱跑步 解题思路见代码. NOIP2016代码整合

  5. [日记&做题记录]-Noip2016提高组复赛 倒数十天

    写这篇博客的时候有点激动 为了让自己不颓 还是写写日记 存存模板 Nov.8 2016 今天早上买了两个蛋挞 吃了一个 然后就做数论(前天晚上还是想放弃数论 但是昨天被数论虐了 woc noip模拟赛 ...

  6. 【NOIP2016提高组】 Day2 T3 愤怒的小鸟

    题目传送门:https://www.luogu.org/problemnew/show/P2831 说个题外话:NOIP2014也有一道题叫做愤怒的小鸟. 这题自测时算错了eps,导致被卡了精度,从1 ...

  7. NOIP2016提高组复赛C 愤怒的小鸟

    题目链接:http://uoj.ac/problem/265 题目大意: 太长了不想概括... 分析: 状压DP的模板题,把所有可能的抛物线用二进制表示,然后暴力枚举所有组合,详情见代码内注释 代码如 ...

  8. 【NOIP2016提高组day2】愤怒的小鸟

    分析 Kiana最近沉迷于一款神奇的游戏无法自拔. 简单来说,这款游戏是在一个平面上进行的. 有一架弹弓位于 (0, 0) 处,每次Kiana可以用它向第一象限发射一只红色的小鸟, 小鸟们的飞行轨迹均 ...

  9. 【noip2016提高组day2T3】【愤怒的小鸟】状压dp转移时的集合包含

    (上不了p站我要死了,图来自百度,侵权度娘背锅) 调死我了... 标题就说明了,死在了集合包含上.因为这道题与其他的状压题不同,其他的题基本上都是要求集合不重合,而这道题完全是可以的. 废话不多说,先 ...

随机推荐

  1. 使用Mongodb+Shiro+SpringMVC实现动态权限分配

    此次的文档只对Mongodb整合Shiro并且实现动态权限分配做整理,其它的内容以后会补上. 第一步.创建在web.xml中配置 Spring .Shiro shiroFilter 过滤器是用来将请求 ...

  2. 详解tomcat的连接数与线程池

    前言 在使用tomcat时,经常会遇到连接数.线程数之类的配置问题,要真正理解这些概念,必须先了解Tomcat的连接器(Connector). 在前面的文章 详解Tomcat配置文件server.xm ...

  3. WebService-axis2

    WebService框架有好多,常用的cxf,axis2等,axis2的配置过程相对简单,不用编写接口,在实现.只需要一个Service服务类即可.配置过程大致如下: 1,导入jar包(这里我是把ax ...

  4. Python 列表浅拷贝与深拷贝

    浅拷贝 shallow copy 和深拷贝 deep copy list.copy() 浅拷贝:复制此列表(只复制一层,不会复制深层对象) 等同于 L[:] 举例: 浅拷贝: a = [1.1, 2. ...

  5. 前后端分手大师——MVVM 模式

    之前对 MVVM 模式一直只是模模糊糊的认识,正所谓没有实践就没有发言权,通过这两年对 Vue 框架的深入学习和项目实践,终于可以装B了有了拨开云雾见月明的感觉. 简而言之 Model–View–Vi ...

  6. .NET读取Excel文件的三种方法的区别

    ASP.NET读取Excel文件方法一:采用OleDB读取Excel文件: 把Excel文件当做一个数据源来进行数据的读取操作,实例如下: public DataSet ExcelToDS(strin ...

  7. Socket网络编程之概述理解

    今天主要讲讲什么是socket网络编程 socketde 英文原义是"孔"或者"插座".是进程通讯的一种方式,即调用这个网络库的一些API函数实现分布在不同主机 ...

  8. [转载] Linux的Top命令解析

    转载自http://www.jb51.net/LINUXjishu/34604.html.http://blog.csdn.net/hello_yang213/article/details/7455 ...

  9. [转载] ZooKeeper实现分布式队列Queue

    转载自http://blog.fens.me/zookeeper-queue/ 让Hadoop跑在云端系列文章,介绍了如何整合虚拟化和Hadoop,让Hadoop集群跑在VPS虚拟主机上,通过云向用户 ...

  10. web前端-----第二弹CSS

    web前端之CSS样式 CSS 语法 CSS 规则由两个主要的部分构成:选择器,以及一条或多条声明. ''' selector { property: value; property: value; ...