NOIp2016 D2T3 愤怒的小鸟【搜索】(网上题解正解是状压)
没啥别的想法,感觉就是搜索,经过原点的抛物线已知两个点就可以求出解析式,在还没有被打下来的两个猪之间随意配对,确定解析式之后标记在这个抛物线下被打下来的猪。
猪也可以单独用一个抛物线打下来。
和之前写斗地主的搜索模式差不多,$TLE60pts$
就是要注意一下精度问题,$get$一个新点:浮点数的判等不能用$==$,可能会有精度误差,只差一点点的情况下可以认为他们是相等的,精度大概就取$EPS=1e-8$
bool dy(double a,double b)
{//浮点误差
return Abs(a-b)<EPS;
}
//暴搜 60pts
#include<cstdio>
#include<algorithm>
#include<vector>
#include<cstring>
#include<queue>
#include<map>
#include<iostream>
using namespace std;
#define ll long long
#define INF 0x3f3f3f3f
#define N 20
#define EPS 1e-8
double Abs(double a)
{
if(a>=0.0) return a;
return -a;
}
bool dy(double a,double b)
{//浮点误差
return Abs(a-b)<EPS;
}
int rd()
{
int f=,s=;char c=getchar();
while(c<''||c>''){if(c=='-') f=-;c=getchar();}
while(c>=''&&c<=''){s=(s<<)+(s<<)+(c^);c=getchar();}
return f*s;
}
int n,m,ans;
struct node{
double x,y;
}pt[N];
bool vis[N];
int tmp[N],cnt;
void dfs(int k)//发射小鸟的次数
{
if(k>ans) return ;
for(int i=;i<=n;i++)
{
if(vis[i]) continue;
vis[i]=;
for(int j=i+;j<=n;j++)
{
if(vis[j]) continue;
double x1=pt[i].x,x2=pt[j].x,y1=pt[i].y,y2=pt[j].y;
double a=(y1*x2-y2*x1)/(x1*x2*x1-x1*x2*x2);
if(a>=) continue;//vis[j]=1要放在这个后面 否则不构成继续递归的条件也还是标记了
double b=(y1*x2*x2-y2*x1*x1)/(x1*x2*x2-x1*x1*x2);
//queue<int>Q;
//while(!Q.empty()) Q.pop();
cnt=;
vis[j]=;
for(int p=;p<=n;p++)
if(dy(pt[p].x*pt[p].x*a+pt[p].x*b,pt[p].y))
{
vis[p]=;
tmp[++cnt]=p;
//Q.push(p);
}
dfs(k+);
vis[j]=;
for(int i=;i<=cnt;i++)
vis[tmp[i]]=;
cnt=;
/*while(!Q.empty())
{
int u=Q.front();Q.pop();
vis[u]=0;
}*/
}
vis[i]=;
}
for(int i=;i<=n;i++)
if(!vis[i]) k++;
ans=min(ans,k);
return ;
}
int main()
{
int T=rd();
while(T--)
{
n=rd(),m=rd();
for(int i=;i<=n;i++)
scanf("%lf %lf",&pt[i].x,&pt[i].y),vis[i]=;
if(n==)
{
puts("");
continue;
}
if(n==)
{
/*
x1*x1*x2*a+x1*x2*b=y1*x2
x2*x2*x1*a+x2*x1*b=y2*x1
(x1*x1*x2-x1*x2*x2)a=y1*x2-y2*x1
x1*x2*(x1-x2)a=y1*x2-y2*x1
*/
if(((pt[].x*pt[].x*(pt[].x-pt[].x))*(pt[].y*pt[].x-pt[].y*pt[].x))<)
puts("");
else puts("");
continue;
}
if(m==||m==)
{
ans=n;
//for(int i=1;i<=n;i++)
// printf("%f %f %d\n",pt[i].x,pt[i].y,vis[i]);
dfs();
printf("%d\n",ans);
}
if(m==)
{
ans=((n+)/+);
dfs();
printf("%d\n",ans);
}
}
return ;
}
Code
然后,改用了以猪头作为...线索(?姑且这么叫着吧,找不到什么更好的词)
把抛物线和没有放抛物线的猪头存下来,每次遍历到猪头的时候就看这个猪头有没有在抛物线上,如果有就不用管他。没有就考虑把这个猪头和前面没有打下来的猪头放在一起看能否组成一个新的开口向下的抛物线,或者让他单着。
感觉每次把前面的猪头取出来放回去的操作改成链表的话,就很想$DLX$了呢。
这种写法可以过,但是我不会证复杂度什么的。
机房$dalao$说用$DLX$+迭代加深不能过....我...也很疑惑...
#include<cstdio>
#include<algorithm>
#include<vector>
#include<cstring>
#include<queue>
#include<map>
#include<iostream>
using namespace std;
#define ll long long
#define INF 0x3f3f3f3f
#define N 20
#define EPS 1e-8
double Abs(double a)
{
if(a>=0.0) return a;
return -a;
}
bool dy(double a,double b)
{//浮点误差
return Abs(a-b)<EPS;
}
int rd()
{
int f=,s=;char c=getchar();
while(c<''||c>''){if(c=='-') f=-;c=getchar();}
while(c>=''&&c<=''){s=(s<<)+(s<<)+(c^);c=getchar();}
return f*s;
}
int n,m,ans;
struct node{
double x,y;
}pt[N]/*猪*/,pwx[N]/*抛物线*/;
int id[N];//单独的猪的标号
void dfs(int k,int u/*抛物线*/,int v/*单独的猪*/)
{
if(u+v>=ans) return ;
if(k>n)
{
ans=min(ans,u+v);
return ;
}
bool flag=;
for(int i=;i<=u;i++)
if(dy(pwx[i].x*pt[k].x*pt[k].x+pwx[i].y*pt[k].x,pt[k].y))
{
dfs(k+,u,v);
flag=;
break;
}
if(flag) return ;//如果已经可以被打掉,就不用管了
//否则就 要么和其它猪形成抛物线 要么自己单独
double x1=pt[k].x,y1=pt[k].y;
for(int i=;i<=v;i++)
{
double x2=pt[id[i]].x,y2=pt[id[i]].y;
if(dy(x1,x2)) continue;
double a=(y1*x2-y2*x1)/(x1*x2*x1-x1*x2*x2);
if(a>=) continue;
double b=(y1*x2*x2-y2*x1*x1)/(x1*x2*x2-x1*x1*x2);
pwx[u+].x=a,pwx[u+].y=b;
int tmp=id[i];
for(int j=i;j<v;j++)
id[j]=id[j+];
dfs(k+,u+,v-);
for(int j=v;j>i;j--)
id[j]=id[j-];
id[i]=tmp;
}
id[v+]=k;
dfs(k+,u,v+);
}
int main()
{
int T=rd();
while(T--)
{
n=rd(),m=rd();
for(int i=;i<=n;i++)
scanf("%lf %lf",&pt[i].x,&pt[i].y);
if(n==)
{
puts("");
continue;
}
if(n==)
{
if(((pt[].x*pt[].x*(pt[].x-pt[].x))*(pt[].y*pt[].x-pt[].y*pt[].x))<)
puts("");
else puts("");
continue;
}
ans=n;
dfs(,,);
printf("%d\n",ans);
}
return ;
}
Code
至于正解的什么状压,不如...放飞象征和平的鸽子?
NOIp2016 D2T3 愤怒的小鸟【搜索】(网上题解正解是状压)的更多相关文章
- NOIP2016 D2-T3 愤怒的小鸟
看了题解之后知道,是状压dp. 一.首先预处理一个$2^n$次方的fpow[]数组 fpow[]=; ;i<=;i++)fpow[i]=(fpow[i-]<<); 二.然后预处理一个 ...
- 【NOIP2016】愤怒的小鸟 搜索
题目描述 Kiana 最近沉迷于一款神奇的游戏无法自拔. 简单来说,这款游戏是在一个平面上进行的. 有一架弹弓位于 (0,0)(0,0) 处,每次 Kiana 可以用它向第一象限发射一只红色的小鸟,小 ...
- 计蒜客模拟赛D2T3 蒜头君救人:用bfs转移状压dp
题目链接:https://nanti.jisuanke.com/t/16444 题意: 蒜头君是一个乐于助人的好孩子,这天他所在的乡村发生了洪水,有多名村民被困于孤岛上,于是蒜头君决定去背他们离开困境 ...
- 【题解】P3959 宝藏 - 状压dp / dfs剪枝
P3959 宝藏 题目描述 参与考古挖掘的小明得到了一份藏宝图,藏宝图上标出了 n 个深埋在地下的宝藏屋, 也给出了这 n 个宝藏屋之间可供开发的m 条道路和它们的长度. 小明决心亲自前往挖掘所有宝 ...
- Bzoj 3813 奇数国 题解 数论+线段树+状压
3813: 奇数国 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 748 Solved: 425[Submit][Status][Discuss] ...
- 洛谷P2831 愤怒的小鸟——贪心?状压DP
题目:https://www.luogu.org/problemnew/show/P2831 一开始想 n^3 贪心来着: 先按 x 排个序,那么第一个不就一定要打了么? 在枚举后面某一个,和它形成一 ...
- 【状压DP】【P2831】【NOIP2016D2T3】愤怒的小鸟
传送门 Description Kiana 最近沉迷于一款神奇的游戏无法自拔. 简单来说,这款游戏是在一个平面上进行的. 有一架弹弓位于 $(0,0)$ 处,每次 Kiana 可以用它向第一象限发射一 ...
- 【NOIP2017】宝藏 题解(状压DP)
题目描述 参与考古挖掘的小明得到了一份藏宝图,藏宝图上标出了 nnn 个深埋在地下的宝藏屋, 也给出了这 nnn 个宝藏屋之间可供开发的m mm 条道路和它们的长度. 小明决心亲自前往挖掘所有宝藏屋中 ...
- 分享网上搜到的Oracle中对判定条件where 1=1的正解
今天在网上找到了Oracle中对判定条件where 1=1的正解,粘贴出来和大家分享下 1=1 是永恒成立的,意思无条件的,也就是说在SQL语句里有没有这个1=1都可以. 这个1=1常用于应用程序根据 ...
随机推荐
- python2.6切换python3.4的操作记录
python2.6切换python3.4的操作记录 之所以写这个记录,源于昨日下午,因为开发人员使用脚本清洗数据,而导致生产环境数据异常,需要根据binlog日志进行回滚.但在使用binlog2sql ...
- [Spring Boot] Aspect Intro
Aspect-Oriented Programming (AOP) complements Object-Oriented Programming (OOP) by providing another ...
- EOS dice移到1.8版本的修改汇总
EOS dice移到1.8版本的修改汇总 1. CORE_SYMBOL 被去掉了,需要自己在文件中声明eg: uint64_t string_to_symbol_c(uint8_t precision ...
- 嵌入式实时操作系统VxWorks入门――开发环境构建[转]
VxWorks 操作系统是美国WindRiver公司于1983年设计开发的一种嵌入式实时操作系统(RTOS),它以其良好的可靠性和卓越的实时性被广泛地应用在通 信.军事.航空.航天等高精尖技术及实时性 ...
- 卸载brew
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/uninst ...
- mac重启php7.0
killall php-fpm /usr/local/opt/php70/sbin/php70-fpm restart
- sql查询的常用语句
一.基础 1.说明:创建数据库 CREATE DATABASE database-name 2.说明:删除数据库 drop database 数据库名 3.说明:备份sql server --- 创建 ...
- [心得]暑假DAY 5
好久没更新博客了 最近事情太多太多 tarjan进阶,点双边双 T2压力 最大坑点:点双缩点 它不是直接把割点连成树(割点会有环) 而是用割点作”中介“,联接点双构成一颗树(所谓圆方树) 接着在上面进 ...
- Liunx 命令之链接操作
Linux 系统中有软链接和硬链接两种特殊的"文件". 软链接可以看作是Windows中的快捷方式,可以让你快速链接到目标档案或目录. 硬链接则透过文件系统的inode来产生新档名 ...
- Nodepad++中将Tab键替换为空格
Nodepad++是一个非常优秀的文本编辑工具,本人经常使用其编辑shell脚本,如果不进行设置,Tab键和空格混用,脚本上传到linux后,格式错乱,不容易查看. 设置方式 菜单栏选择"设 ...