【NOIP2016提高组】愤怒的小鸟
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提高组】愤怒的小鸟的更多相关文章
- [NOIp2016提高组]愤怒的小鸟
题目大意: 平面直角坐标系的第一象限有n(n<=18)个点,你可以每次给出一个形如y=ax^2+bx的函数把经过这条函数的点消掉,问消掉所有的点至少要多少函数? 思路: 枚举每两个点对,可以唯一 ...
- 【题解】NOIP2016提高组 复赛
[题解]NOIP2016提高组 复赛 传送门: 玩具谜题 \(\text{[P1563]}\) 天天爱跑步 \(\text{[P1600]}\) 换教室 \(\text{[P1850]}\) 组合数问 ...
- 【题解】NOIP2016 提高组 简要题解
[题解]NOIP2016 提高组 简要题解 玩具迷题(送分) 用异或实现 //@winlere #include<iostream> #include<cstdio> #inc ...
- NOIP2016提高组解题报告
NOIP2016提高组解题报告 更正:NOIP day1 T2天天爱跑步 解题思路见代码. NOIP2016代码整合
- [日记&做题记录]-Noip2016提高组复赛 倒数十天
写这篇博客的时候有点激动 为了让自己不颓 还是写写日记 存存模板 Nov.8 2016 今天早上买了两个蛋挞 吃了一个 然后就做数论(前天晚上还是想放弃数论 但是昨天被数论虐了 woc noip模拟赛 ...
- 【NOIP2016提高组】 Day2 T3 愤怒的小鸟
题目传送门:https://www.luogu.org/problemnew/show/P2831 说个题外话:NOIP2014也有一道题叫做愤怒的小鸟. 这题自测时算错了eps,导致被卡了精度,从1 ...
- NOIP2016提高组复赛C 愤怒的小鸟
题目链接:http://uoj.ac/problem/265 题目大意: 太长了不想概括... 分析: 状压DP的模板题,把所有可能的抛物线用二进制表示,然后暴力枚举所有组合,详情见代码内注释 代码如 ...
- 【NOIP2016提高组day2】愤怒的小鸟
分析 Kiana最近沉迷于一款神奇的游戏无法自拔. 简单来说,这款游戏是在一个平面上进行的. 有一架弹弓位于 (0, 0) 处,每次Kiana可以用它向第一象限发射一只红色的小鸟, 小鸟们的飞行轨迹均 ...
- 【noip2016提高组day2T3】【愤怒的小鸟】状压dp转移时的集合包含
(上不了p站我要死了,图来自百度,侵权度娘背锅) 调死我了... 标题就说明了,死在了集合包含上.因为这道题与其他的状压题不同,其他的题基本上都是要求集合不重合,而这道题完全是可以的. 废话不多说,先 ...
随机推荐
- PAT-甲级-1002
1.来,先看题,https://www.patest.cn/contests/pat-a-practise/1002. 2.需要注意的地方只有一个:两个多项式相加之后,系数可能为零,这些项不应该出现在 ...
- http 500错误怎么解决方法
出现500错误的原因是很多的,一般来说,如果程序出错,那么在浏览器内会返回给用户一个友好的错误提示,统一称之为服务器500错误. 解决的方法就是您必须在http中能够正确的获得错误信息,方法为:请打开 ...
- shapes 不规则边界
CSS基本形状都是矩形,CSS shapes允许开发者用定制的路径来包裹内容,例如圆形,椭圆,多边形等. 形状可以自定义也可以从图片中推断 从图片推断,例如可以让文字按照图片形状来浮动到一边: ...
- touchmove Bug 工作遇到
touchmove在安卓浏览器上只会触发一次,需要preventDefault() touchmove events in Android web browsers have a really ser ...
- Robotframework自动化系统:筛选结果数量统计
Robotframework自动化系统:筛选结果数量统计 上一个节点已经可以随机选中某一个下拉框的值,我们在使用evaluate随机数的时候需要计算下拉选项总数,这时候我们是手工计算输入的:这时候如果 ...
- ORACLE使用数据泵导入导出部分表
1.导出名字为A的表(这里会导出SEQUENCES及FUNCTION等内容) expdp TEST/TEST@orcl schemas=TEST dumpfile=TEST.dmp DIRECTORY ...
- java 数据分页
分页逻辑 import lombok.Data; /** * User eric * Date * Email yq@aso.ren */ @Data public class PageHelper ...
- ContextLoaderListener - 运行原理
基本概念: servletContext:http://blog.csdn.net/yjw757174266/article/details/45072975 1. 使用ContextLoaderL ...
- sql2012笔记
收缩数据库日志文件1.数据库右键-->Options-->Revovery model =Full 改成 Simple2.数据库右键-->Tasks-->Shrink--> ...
- C#中抽象类与接口的区别
1.面向接口编程和面向对象编程是什么关系 首先,面向接口编程和面向对象编程并不是平级的,它并不是比面向对象编程更先进的一种独立的编程思想,而是附属于面向对象思想体系,属于其一部分.或者说,它是面向对象 ...