愤怒的小鸟

Description:
给你\(n<=18\)个小猪,发射的小鸟轨迹为抛物线,求最小用多少个小鸟可以将小猪全部干掉
看到n很小,我想到了搜索,于是我用\(dfs\)枚举出,每个抛物线打掉的小猪集合然后判断他的合法性,结果TLE成了50分,mmp,瞄了一眼题解,看到他是枚举小猪,来确定抛物线,感觉妙了很多,于是我写了如下的
code:
  1. #include<cstdio>
  2. #include<cstring>
  3. #include<iostream>
  4. using namespace std;
  5. const double eps=0.0000001;
  6. int t,n,m,ans;
  7. double x[20],y[20],a[20],b[20];
  8. bool vis[20];
  9. inline double fabs(double x){
  10. if(x<0)return -x;
  11. else return x;
  12. }
  13. inline void dfs(int pos,int num,int cnt){
  14. //当前决策第几个位置,构造了多少个抛物线,剩下几个独立的
  15. if(pos>n){
  16. ans=min(ans,num+cnt);
  17. return ;
  18. }
  19. bool flag=0;
  20. for(int i=1;i<=num;++i){//枚举是否可以被前面的抛物线覆盖
  21. double xx=a[i]*x[pos]*x[pos]+b[i]*x[pos];
  22. double yy=y[pos];
  23. if(fabs(fabs(xx)-fabs(yy))<=eps&&(xx*yy>0)){
  24. flag=1;
  25. vis[pos]=1;//不独立
  26. dfs(pos+1,num,cnt-1);
  27. vis[pos]=0;
  28. break;
  29. }
  30. }
  31. if(flag)return ;
  32. for(int i=1;i<pos;++i){
  33. if(vis[i])continue;//不独立
  34. double a1=x[i];
  35. double b1=y[i];
  36. double a2=x[pos];
  37. double b2=y[pos];
  38. double aa=(b1*a2-b2*a1)/(a1*a1*a2-a1*a2*a2);
  39. double bb=(a1*a1*b2-a2*a2*b1)/(a1*a1*a2-a2*a2*a1);
  40. if(aa>=0)continue;//不可行
  41. a[num+1]=aa;
  42. b[num+1]=bb;//可行
  43. vis[i]=vis[pos]=1;//不独立了
  44. dfs(pos+1,num+1,cnt-2);
  45. a[num+1]=0;
  46. b[num+1]=0;
  47. vis[i]=vis[pos]=0;//回溯
  48. }
  49. dfs(pos+1,num,cnt);//自己独立
  50. }
  51. int main(){
  52. scanf("%d",&t);
  53. for(int i=1;i<=t;++i){
  54. scanf("%d%d",&n,&m);
  55. for(int i=1;i<=n;++i)scanf("%lf%lf",&x[i],&y[i]);
  56. ans=0x3f3f3f3f;
  57. dfs(1,0,n);
  58. cout<<ans<<endl;
  59. }
  60. }
80分还是TLE
于是乎,又瞄了一眼题解,他加了一个最优性剪枝\(num+cnt>=ans,return ;\)
于是我也加了一个,这下可惨了,一下WA成了40
注意看我的代码,\(dfs(pos+1,num,cnt-1)\text{&&}dfs(pos+1,num+1,cnt-2)\text{&&}dfs(pos+1,num,cnt)\)
\(num+cnt\)的总和是变小了,如果使用最优性剪枝,有可能将最优值剪掉
仔细比较题解和我的代码,他并不是把所有的小猪刚开始都变成独立的,这样对于一个新小猪,他的code

\(dfs(pos+1,num,cnt)\text{&&} dfs(pos+1,num+1,cnt-1)\text{&&}dfs(pos+1,num,cnt+1)\)

\(num+cnt\)的总和单调不降,可以使用最优性剪枝
我是上来就把所有小猪看成独立,而他是将小猪后放进去
code:
  1. #include<cstdio>
  2. #include<cstring>
  3. #include<iostream>
  4. #include<cmath>
  5. using namespace std;
  6. const double eps=1e-8;
  7. int t,n,m,ans;
  8. double x[20],y[20],a[20],b[20],xx[20],yy[20];
  9. inline void dfs(int pos,int num,int cnt){
  10. if(num+cnt>=ans)return ;//最优性剪枝
  11. if(pos>n){
  12. ans=num+cnt;
  13. return ;
  14. }//边界
  15. bool flag=0;
  16. for(int i=1;i<=num;++i){//枚举是否可以被前面的抛物线覆盖
  17. double xx=a[i]*x[pos]*x[pos]+b[i]*x[pos];
  18. double yy=y[pos];
  19. if(fabs(xx-yy)<eps){
  20. dfs(pos+1,num,cnt);
  21. flag=1;
  22. break;
  23. }
  24. }
  25. if(!flag){
  26. for(int i=1;i<=cnt;++i){
  27. double a1=xx[i];
  28. double b1=yy[i];
  29. double a2=x[pos];
  30. double b2=y[pos];
  31. if(fabs(a1-a2)<=eps)continue;
  32. double aa=(b1*a2-b2*a1)/(a1*a1*a2-a1*a2*a2);
  33. double bb=(a1*a1*b2-a2*a2*b1)/(a1*a1*a2-a2*a2*a1);
  34. if(aa>=0)continue;//不可行
  35. a[num+1]=aa;
  36. b[num+1]=bb;
  37. double va=xx[i];
  38. double vb=yy[i];
  39. for(int j=i;j<cnt;++j){
  40. xx[j]=xx[j+1];
  41. yy[j]=yy[j+1];
  42. }
  43. dfs(pos+1,num+1,cnt-1);
  44. for(int j=cnt;j>i;j--)
  45. {
  46. xx[j]=xx[j-1];
  47. yy[j]=yy[j-1];
  48. }
  49. xx[i]=va;
  50. yy[i]=vb;
  51. }
  52. xx[cnt+1]=x[pos];
  53. yy[cnt+1]=y[pos];
  54. dfs(pos+1,num,cnt+1);//自己独立
  55. }
  56. }
  57. int main(){
  58. scanf("%d",&t);
  59. for(int i=1;i<=t;++i){
  60. scanf("%d%d",&n,&m);
  61. for(int i=1;i<=n;++i)scanf("%lf%lf",&x[i],&y[i]);
  62. ans=0x3f3f3f3f;
  63. dfs(1,0,0);
  64. cout<<ans<<endl;
  65. }
  66. }

搜索:状态要定好,剪枝要想好

NOIP愤怒的小鸟的更多相关文章

  1. Noip 2016 愤怒的小鸟 题解

    [NOIP2016]愤怒的小鸟 时间限制:1 s   内存限制:256 MB [题目描述] Kiana最近沉迷于一款神奇的游戏无法自拔. 简单来说,这款游戏是在一个平面上进行的. 有一架弹弓位于(0, ...

  2. [luogu2831][noip d2t3]愤怒的小鸟_状压dp

    愤怒的小鸟 noip-d2t3 luogu-2831 题目大意:给你n个点,问最少需要多少条经过原点的抛物线将其覆盖. 注释:1<=点数<=18,1<=数据组数<=30.且规定 ...

  3. [NOIp 2016]愤怒的小鸟

    Description Input Output Sample Input 22 01.00 3.003.00 3.005 21.00 5.002.00 8.003.00 9.004.00 8.005 ...

  4. 【NOIP 2016】Day2 T3 愤怒的小鸟

    Problem Description \(Kiana\) 最近沉迷于一款神奇的游戏无法自拔. 简单来说,这款游戏是在一个平面上进行的. 有一架弹弓位于 \((0,0)\) 处,每次 \(Kiana\ ...

  5. 【NOIP】提高组2016 愤怒的小鸟

    [题意]Universal Online Judge [算法]状态压缩型DP [题解]看数据范围大概能猜到是状压了. 根据三点确定一条抛物线,枚举两个点之间的抛物线,再枚举有多少点在抛物线上(压缩为状 ...

  6. LUOGU P2831 愤怒的小鸟 (NOIP 2016)

    题面 题解 好像昨天wxl大爷讲的是O(Tn*2^n)的做法,后来没想通,就自己写了个O(Tn^2*2^n)的暴力状压, 莫名其妙过了??数量级二十亿??懵逼,可能到了CCF老爷机上就T了.dp[S] ...

  7. NOIP提高组2016 D2T3 【愤怒的小鸟】

    貌似还没有写过状压DP的题目,嗯,刚好今天考了,就拿出来写一写吧. 题目大意: 额,比较懒,这次就不写了... 思路分析: 先教大家一种判断题目是不是状压DP的方法吧. 很简单,那就是--看数据范围! ...

  8. Noip 2016

    Day1 思路: 大致是 把一个环拆成链, 找某个人无非是向右找或向左找(即对当前点加或减) 若加上要移动的位置后坐标大于总人数, 就把当前坐标减去总人数, 若减去要移动的位置后坐标小于0, 就把当前 ...

  9. 5月14日 绿城育华NOIP巨石杯试卷解析

    [题外话] 感谢UBUNTU为保存程序做出贡献:https://paste.ubuntu.com : 感谢洛谷OJ的私人题库保存题面:https://www.luogu.org : 现在我的题解的所有 ...

随机推荐

  1. poj2280--Amphiphilic Carbon Molecules(扫描线+极角排序+转换坐标)

    题目链接:id=2280">点击打开链接 题目大意:给出n个点的坐标.每一个点有一个值0或者1,如今有一个隔板(无限长)去分开着n个点,一側统计0的个数,一側统计1的个数,假设点在板上 ...

  2. Unity3D的场景单位 和 3D建模软件的单位 之间的关系

    转载自 : http://www.ceeger.com/Unity/Doc/2011/3D_to_Unity.html Date:2011-08-24 03:52 Unity的系统单位为米,其他3D软 ...

  3. angularjs 指令2

    <!DOCTYPE HTML> <html ng-app="myApp"> <head> <meta http-equiv="C ...

  4. bzoj1800: [Ahoi2009]fly 飞行棋(乱搞)

    1800: [Ahoi2009]fly 飞行棋 题目:传送门 题解: 大水题,早上签个到 没什么好说的...搞个前缀和,算个周长... 周长为奇数肯定误解啊废话QWQ 那么看到n<=20,还不暴 ...

  5. [luogu P3360] 偷天换日 解题报告(树形DP)

    题目链接:https://www.luogu.org/problemnew/show/P3360 题解: 首先我们把边上的消耗放到向下的点上,如果是叶子节点的话就先做一次0/1背包 发现这是一颗二叉树 ...

  6. linux中的挂载是什么意思?通俗点讲

    mount /dev/sda1 /mnt解释:mount 就是挂载命令,/dev/sda1是要挂载的磁盘分区,/mnt是要绑定的目录挂载后就能到目录/mnt去访问磁盘分区/dev/sda1里面的资料了 ...

  7. SharePoint 修改完或制作完一定要发布

    设置了匿名访问但是网站就是需要登录,找了很多问题. 首先想到的映射问题,然后努力检查,最后把代码删掉,然后把站删掉,最后测试出来问题. 点击上方[网站设置] 把修改过的文件发布. 母版也和布局页 一定 ...

  8. View简介

    1.View 是所有widget类的基类 2.View的坐标 根据上面的图应该会比较容易明白,图中屏幕上放了一个ViewGroup布局,里面有个View控件 getTop:获取到的,是view自身的顶 ...

  9. <Three.js>(第一节)环境搭建

    Three.js顾名思义3D的js库.是运行在浏览器的基于webgl的3D引擎.该引擎是github上的一个开源项目,下载地址:https://github.com/mrdoob/three.js/ ...

  10. mac终端(terminal)里的快捷键

    Command + K 清屏 Command + T 新建标签 Command +W 关闭当前标签页 Command + S 保存终端输出 Command + D 垂直分隔当前标签页 Command ...