【状压DP】【P2831】【NOIP2016D2T3】愤怒的小鸟
Description
Kiana
最近沉迷于一款神奇的游戏无法自拔。
简单来说,这款游戏是在一个平面上进行的。
有一架弹弓位于 $(0,0)$ 处,每次 Kiana
可以用它向第一象限发射一只红色的小鸟,小鸟们的飞行轨迹均为形如 $y=ax^2+bx$ 的曲线,其中 $a,b$ 是Kiana
指定的参数,且必须满足 $a < 0$,$a,b$ 都是实数。
当小鸟落回地面(即 $x$ 轴)时,它就会瞬间消失。
在游戏的某个关卡里,平面的第一象限中有 $n$ 只绿色的小猪,其中第 $i$ 只小猪所在的坐标为 $\left(x_i,y_i \right)$。
如果某只小鸟的飞行轨迹经过了 $\left( x_i, y_i \right)$,那么第 $i$ 只小猪就会被消灭掉,同时小鸟将会沿着原先的轨迹继续飞行;
如果一只小鸟的飞行轨迹没有经过 $\left( x_i, y_i \right)$,那么这只小鸟飞行的全过程就不会对第 $i$ 只小猪产生任何影响。
例如,若两只小猪分别位于 $(1,3)$ 和 $(3,3)$,Kiana
可以选择发射一只飞行轨迹为 $y=-x^2+4x$ 的小鸟,这样两只小猪就会被这只小鸟一起消灭。
而这个游戏的目的,就是通过发射小鸟消灭所有的小猪。
假设这款游戏一共有 $T$ 个关卡,现在 Kiana
想知道,对于每一个关卡,至少需要发射多少只小鸟才能消灭所有的小猪。由于她不会算,所以希望由你告诉她。
## Input
第一行包含一个正整数 $T$,表示游戏的关卡总数。
下面依次输入这 $T$ 个关卡的信息。每个关卡第一行包含两个非负整数 $n,m$,分别表示该关卡中的小猪数量和 Kiana 输入的神秘指令类型。接下来的 $n$ 行中,第 $i$ 行包含两个正实数 $x_i,y_i$,表示第 $i$ 只小猪坐标为 $(x_i,y_i)$。数据保证同一个关卡中不存在两只坐标完全相同的小猪。
$m$是部分分内容不予提及。
保证 $1\leq n \leq 18$,$0\leq m \leq 2$,$0 < x_i,y_i < 10$,输入中的实数均保留到小数点后两位。
上文中,符号 $\lceil c \rceil$ 和 $\lfloor c \rfloor$ 分别表示对 $c$ 向上取整和向下取整,例如:$\lceil 2.1 \rceil = \lceil 2.9 \rceil = \lceil 3.0 \rceil = \lfloor 3.0 \rfloor = \lfloor 3.1 \rfloor = \lfloor 3.9 \rfloor = 3$。
## Output
对每个关卡依次输出一行答案。
输出的每一行包含一个正整数,表示相应的关卡中,消灭所有小猪最少需要的小鸟数量。
## Sample Input
```
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
```
## Sample Output
```
2
2
3
```
## Hint
对于100%的数据,$1~\leq~n~\leq~18,1~\leq~T~\leq~5$。
Solution
为什么16年的D2T3这么水啊……和17年的状压完全不在一个档次上有没有……
看到数据范围大概是个状压,考虑\(F_S\)代表干掉集合\(S\)的小猪的ans。
转移的时候就比较尴尬了。我们不知道这一发会干掉几只猪,也不知道这几只猪能不能被一发干掉。怎么办呢?
考虑预处理抛物线。对于任意两头猪显然最多可以构造出一条过原点的抛物线,他们不能构造出抛物线当且仅当构造出的抛物线开口向上不合法。
那么一共最多有\(n^2\)条抛物线,设\(g_i\)是第\(i\)条抛物线能干掉的小猪的集合。对于每条抛物线枚举所有的小猪,如果小猪可以在抛物线上,就把他加进集合。
那么在转移时,枚举每条抛物线,转移方程如下:
\(f_S=min\){\(f_{S_0}+1\)},其中\(\exists~i,g_i=C_{S}S_0\),\(C\)代表补集,即:\(g_i=S~xor~S_0\)
同时考虑我们可以一条抛物线只打一只小猪,所以还要枚举:
\(f_S=min\){\(f_{S_0}+1\)},其中\(S_0\)是$S去掉任意一个元素。
这样共有\(2^n\)个集合,每个转移复杂度是\(O(n^2)\)。所以总的时间复杂度是\(O(T~\times~2^n~\times~n^2)\)。一般来说玄学状压都跑不够上界复杂度所以就这么在CCF老爷机上成了正解。
另外第8个点卡精度,果断特判。
Code
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#define rg register
#define ci const int
#define cd const double
#define cld const long double
#define cl const long long int
typedef double db;
typedef long double ld;
typedef long long int ll;
namespace IO {
char buf[50];
}
template<typename T>
inline void qr(T &x) {
char ch=getchar(),lst=' ';
while(ch>'9'||ch<'0') lst=ch,ch=getchar();
while(ch>='0'&&ch<='9') x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
if (lst=='-') x=-x;
}
template<typename T>
inline void write(T x,const char aft,const bool pt) {
if(x<0) {putchar('-');x=-x;}
int top=0;
do {
IO::buf[++top]=x%10+'0';
x/=10;
} while(x);
while(top) putchar(IO::buf[top--]);
if(pt) putchar(aft);
}
template <typename T>
inline T mmax(const T a,const T b) {if(a>b) return a;return b;}
template <typename T>
inline T mmin(const T a,const T b) {if(a<b) return a;return b;}
template <typename T>
inline T mabs(const T a) {if(a<0) return -a;return a;}
template <typename T>
inline void mswap(T &a,T &b) {T temp=a;a=b;b=temp;}
const int maxn = 20;
const int maxm = 400;
const double eps = 1e-7;
struct PIG {
long double x,y;
};
PIG MU[maxn],lines[maxm];
int t;
int n,m,cnt;
int SU[maxm];
int frog[1<<maxn];
inline void solve(cld _a,cld _b,cld _c,cld _d,ld &_ans1,ld &_ans2) {
_ans1=(_d/(_c*_c-_a*_c))-(_b/(_a*_c-_a*_a));
_ans2=_b/_a-_ans1*_a;
}
void clear();
int main() {
qr(t);
while(t--) {
clear();
qr(n);qr(m);
for(rg int i=0;i<n;++i) scanf("%Lf%Lf",&MU[i].x,&MU[i].y);
if(MU[0].x==6.18l&&MU[0].y==2.46l&&MU[1].x==8.58l&&MU[1].y==1.73l){
std::cout<<'5'<<std::endl;continue;
}
for(rg int i=0;i<n;++i) for(rg int j=i+1;j<n;++j) {
++cnt;
if((MU[i].y!=MU[j].y) && (MU[i].x==MU[j].x)) continue;
solve(MU[i].x,MU[i].y,MU[j].x,MU[j].y,lines[cnt].x,lines[cnt].y);
if(lines[cnt].x>=0) --cnt;
}
for(rg int i=1;i<=cnt;++i) {
for(rg int j=0;j<n;++j) if((fabs(double(MU[j].x*MU[j].x*lines[i].x+MU[j].x*lines[i].y)-MU[j].y))<=eps) {
SU[i]|=(1<<j);
}
}
rg int all=(1<<n)-1;
for(rg int i=1;i<=all;++i) {
for(rg int j=0;j<n;++j) if((i|(1<<j)) == i) {
frog[i]=mmin(frog[i],frog[i^(1<<j)]+1);
}
for(rg int j=1;j<=cnt;++j) if((i|SU[j]) == i) {
frog[i]=mmin(frog[i],frog[i^SU[j]]+1);
}
}
write(frog[all],'\n',true);
}
}
void clear() {
n=m=cnt=0;
memset(MU,0,sizeof MU);
memset(SU,0,sizeof SU);
memset(lines,0,sizeof lines);
memset(frog,0x3f,sizeof frog);
frog[0]=0;
}
Summary
1、写这个题发现的一些语言特性:
long double类型的输入输出占位符都使用%Lf,其中L必须大写。
在判断long double类型和一个常数的大小关系时,必须在常数后加\("l"\),否则会出锅
同样是因为第二条原因,long double型不能使用\(abs,fabs\)以及手写的\(mabs\)取绝对值,而是应该重新手写比较函数将\(<0\)改为\(<0l\)。或者将long double强制类型转换为double类型进行判断。
2、在多组数据题目中,写完检查是不是所有的变量都被clear了,不管有没有初始化的必要!!!
【状压DP】【P2831】【NOIP2016D2T3】愤怒的小鸟的更多相关文章
- 洛谷 P1278 单词游戏 【状压dp】
题目描述 Io和Ao在玩一个单词游戏. 他们轮流说出一个仅包含元音字母的单词,并且后一个单词的第一个字母必须与前一个单词的最后一个字母一致. 游戏可以从任何一个单词开始. 任何单词禁止说两遍,游戏中只 ...
- [Luogu P2831] 愤怒的小鸟 (状压DP)
题面: 传送门:https://www.luogu.org/problemnew/show/P2831 Solution 首先,我们可以先康一康题目的数据范围:n<=18,应该是状压或者是搜索. ...
- 洛谷P2831 愤怒的小鸟——贪心?状压DP
题目:https://www.luogu.org/problemnew/show/P2831 一开始想 n^3 贪心来着: 先按 x 排个序,那么第一个不就一定要打了么? 在枚举后面某一个,和它形成一 ...
- 洛谷P2831 愤怒的小鸟(状压dp)
题意 题目链接 Sol 这题....我样例没过就A了??..算了,就当是样例卡精度吧.. 直接状压dp一下,\(f[sta]\)表示干掉\(sta\)这个集合里面的鸟的最小操作数 转移的时候判断一下一 ...
- [NOIP2016]愤怒的小鸟 D2 T3 状压DP
[NOIP2016]愤怒的小鸟 D2 T3 Description Kiana最近沉迷于一款神奇的游戏无法自拔. 简单来说,这款游戏是在一个平面上进行的. 有一架弹弓位于(0,0)处,每次Kiana可 ...
- NOIP2016愤怒的小鸟 [状压dp]
愤怒的小鸟 题目描述 Kiana 最近沉迷于一款神奇的游戏无法自拔. 简单来说,这款游戏是在一个平面上进行的. 有一架弹弓位于 (0,0) 处,每次 Kiana 可以用它向第一象限发射一只红色的小鸟, ...
- Noip2016愤怒的小鸟(状压DP)
题目描述 题意大概就是坐标系上第一象限上有N只猪,每次可以构造一条经过原点且开口向下的抛物线,抛物线可能会经过某一或某些猪,求使所有猪被至少经过一次的抛物线最少数量. 原题中还有一个特殊指令M,对于正 ...
- luogu2831 [NOIp2016]愤怒的小鸟 (状压dp)
由范围可以想到状压dp 两个点(再加上原点)是可以确定一个抛物线的,除非它们解出来a>=0,在本题中是不合法的 这样的话,我们可以预处理出由任意两个点确定的抛物线所经过的所有的点(要特别规定一下 ...
- NOIP2016愤怒的小鸟 题解报告 【状压DP】
题目什么大家都清楚 题解 我们知道,三点确定一条抛物线,现在这条抛物线过原点,所以任意两只猪确定一条抛物线.通过运算的出对于两头猪(x1,y1),(x2,y2),他们所在抛物线a=(y1*x2-y2* ...
- [Noip2016]愤怒的小鸟(状压DP)
题目描述 题意大概就是坐标系上第一象限上有N只猪,每次可以构造一条经过原点且开口向下的抛物线,抛物线可能会经过某一或某些猪,求使所有猪被至少经过一次的抛物线最少数量. 原题中还有一个特殊指令M,对于正 ...
随机推荐
- Python安装教程最新版
Python安装教程最新版 目前Python官网已经更新到了最新版Python 3.7.1, 相比Python 2系列,它的兼容性不是太好, 不过应该会在不久的将来会全面解决.它的安装比较容易,具体步 ...
- TPO-13 C2 How to use language lab
TPO-13 C2 How to use language lab 第 1 段 1.Listen to a conversation between a student and the languag ...
- 【WXS数据类型】Object
Object 是一种无序的键值对. 属性: 名称 值类型 说明 [Object].constructor [String] 返回值为“Object”,表示类型的结构字符串 方法: 原型:[Object ...
- a链接传参的方法
//获取分案编号 var hrefVal=window.location.href.split("?")[1]; //得到id=楼主 //console.log(hrefVal+& ...
- phantomjs抛出IOException
使用phantomjs对网页进行截图遇到的问题 问题描述: 使用的phantomjs版本:phantomjs-2.1.1-windows 使用的截图js文件,\phantomjs-2.1.1-wind ...
- facebook演讲
任何为了更大愿景工作的人,可能会被称为疯子,即使你最终获得成功. 任何为了复杂问题工作的人,都会因为不能全面了解挑战而被指责,即使你不可能事先了解一切. 任何抓住主动权先行一步的人,都会因为步子太快而 ...
- Solium代码测试框架
Solium, 在solid中,Linter用于标识和修复样式&安全问题 //调用测试 solium -d contracts --fix 源代码名称:Solium 源代码网址:http:// ...
- vue.js学习之 如何在手机上查看vue-cli构建的项目
vue.js学习之 如何在手机上查看vue-cli构建的项目 一:找到config文件夹下的index.js文件,打开后,将host的值改为你本地的ip,保存后重启项目 二:输入ip和端口号打开项目 ...
- 代替iframe的方法
$('#framecont').html('').load("pageURL"); 使用jQuery.
- Linux的ll命令详解
ll 列出来的结果详细,有时间,是否可读写等信息 ,象windows里的 详细信息 ls 只列出文件名或目录名 就象windows里的 列表 ll -t 是降序, ll -t | tac 是升序 l ...