题目:https://www.luogu.org/problemnew/show/P2831

状压dp。跑得很慢。(n^2*2^n)

注意只打一只猪的情况。

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cstring>
  4. #include<algorithm>
  5. #include<cmath>
  6. using namespace std;
  7. const int Lm=;const double eps=1e-;
  8. int T,n,dp[(<<Lm)+],lm,tot,tp,list[Lm*Lm+];
  9. struct Node{
  10. double x,y;
  11. }r[Lm+];
  12. //struct Sit{
  13. // int s,cnt;
  14. //}b[(1<<Lm)+5];
  15. //bool cmp(Sit u,Sit v){return u.cnt<v.cnt;}
  16. //int calc(int s)
  17. //{
  18. // int ret=0;while(s)ret++,s-=(s&-s);return ret;
  19. //}
  20. int solve(int i,int j)
  21. {
  22. double y1=r[i].x,x1=y1*y1,z1=r[i].y;
  23. double y2=r[j].x,x2=y2*y2,z2=r[j].y;
  24. double k=x2/x1;y1*=k;z1*=k;y1-=y2;z1-=z2;
  25. double b=z1/y1,a=(z2-b*y2)/x2;
  26. if(a>=)return -;
  27. int ret=;
  28. for(int p=;p<=n;p++)
  29. if(fabs(r[p].x*r[p].x*a+r[p].x*b-r[p].y)<=eps)ret|=(<<(p-));
  30. return ret;
  31. }
  32. void init()
  33. {
  34. // for(int i=0;i<lm;i++)b[i+1].s=i,b[i+1].cnt=calc(i);
  35. // sort(b+1,b+lm,cmp);
  36. tot=;
  37. for(int i=;i<n;i++)list[++tot]=(<<i);///////////
  38. for(int i=;i<=n;i++) for(int j=i+;j<=n;j++)
  39. {
  40. list[++tot]=solve(i,j);
  41. if(list[tot]==-)tot--;
  42. }
  43. memset(dp,,sizeof dp);dp[]=;
  44. }
  45. int main()
  46. {
  47. scanf("%d",&T);
  48. while(T--)
  49. {
  50. scanf("%d%d",&n,&tp);lm=(<<n);
  51. for(int i=;i<=n;i++)scanf("%lf%lf",&r[i].x,&r[i].y);
  52. init();
  53. for(int i=;i<=tot;i++)
  54. for(int s=;s<lm;s++)
  55. dp[s|list[i]]=min(dp[s|list[i]],dp[s]+);
  56. // for(int i=1;i<=lm;i++)
  57. // {
  58. // int s=b[i].s;
  59. // for(int j=1;j<=tot;j++)
  60. // dp[s|list[j]]=min(dp[s|list[j]],dp[s]+1);
  61. // }
  62. printf("%d\n",dp[lm-]);
  63. }
  64. return ;
  65. }

到处看TJ。发现好像是因为弄了很多冗余状态。

让我们分析为什么当前S一定要打掉第一只未打的猪。(n*2^n)

  我们可以把 “前缀连续的1多了一个” 看做更进了一步。反正最后要 “前缀连续的1有n个” ,所以这样看也还行。

  那么不打第一只未打的猪的转移就是同层转移了。这种转移不能使我们离最终状态更近。

  但是它可以让后面的0更少之类的,可能对后面有好的影响。

  分析一下这里:如果现在打了后面、后面再补回来现在这个“第一只未打的猪”可以更优的话,因为打猪的顺序无关,所以可以对应成现在打了“第一只未打的猪”、后面打了本回可能会打的那些猪。

  所以可以n*2^n。(一下子就快了10倍呢)

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cstring>
  4. #include<algorithm>
  5. #include<cmath>
  6. using namespace std;
  7. const int Lm=;const double eps=1e-;
  8. int T,n,dp[(<<Lm)+],lm,tp,list[Lm+][Lm+];
  9. double x[Lm+],y[Lm+];
  10. int solve(int i,int j)
  11. {
  12. double a=(y[i]*x[j]/x[i]-y[j])/(x[i]*x[j]-x[j]*x[j]);
  13. double b=y[i]/x[i]-a*x[i];
  14. if(a>=-eps)return ;
  15. int ret=;
  16. for(int u=;u<=n;u++)
  17. if(fabs(x[u]*x[u]*a+x[u]*b-y[u])<=eps)ret|=(<<(u-));
  18. return ret;
  19. }
  20. void init()
  21. {
  22. for(int i=;i<=n;i++)
  23. {
  24. list[i][i]=(<<(i-));
  25. for(int j=i+;j<=n;j++)
  26. list[i][j]=solve(i,j);
  27. }
  28. memset(dp,,sizeof dp);dp[]=;
  29. }
  30. int main()
  31. {
  32. scanf("%d",&T);
  33. while(T--)
  34. {
  35. scanf("%d%d",&n,&tp);lm=(<<n);
  36. for(int i=;i<=n;i++)scanf("%lf%lf",&x[i],&y[i]);
  37. init();
  38. for(int s=;s<lm;s++)
  39. {
  40. int i;
  41. for(i=;i<=n&&(s&(<<(i-)));i++);
  42. for(int j=i;j<=n;j++)dp[s|list[i][j]]=min(dp[s|list[i][j]],dp[s]+);
  43. }
  44. printf("%d\n",dp[lm-]);
  45. }
  46. return ;
  47. }

但还不够优秀。翻翻洛谷提交记录,看到“文文殿下”惊人的时间,就去学习。

  其实就是用bfs来写。加上第2版的那个优化。

  这样可以得到答案及时退出而不用担心答案不最优(因为是bfs)。

  这大约是利用了  每次转移都只会+1  的性质。能用bfs的话还是它最快呢。(0ms)

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cstring>
  4. #include<algorithm>
  5. #include<cmath>
  6. using namespace std;
  7. const int Lm=,INF=;const double eps=1e-;
  8. int T,n,lm,tp,list[Lm+][Lm+];
  9. int h,t,q[(<<Lm)+],dfn[(<<Lm)+];
  10. double x[Lm+],y[Lm+];
  11. bool vis[(<<Lm)+];
  12. int solve(int i,int j)
  13. {
  14. double a=(y[i]*x[j]/x[i]-y[j])/(x[i]*x[j]-x[j]*x[j]);
  15. double b=(y[i]/x[i]-a*x[i]);
  16. if(a>=-eps)return ;
  17. int ret=;
  18. for(int u=;u<=n;u++)
  19. if(fabs(x[u]*x[u]*a+x[u]*b-y[u])<=eps)ret|=(<<(u-));
  20. return ret;
  21. }
  22. void init()
  23. {
  24. for(int i=;i<=n;i++)
  25. {
  26. list[i][i]=(<<(i-));
  27. for(int j=i+;j<=n;j++)
  28. list[i][j]=solve(i,j);
  29. }
  30. memset(vis,,sizeof vis);
  31. }
  32. void bfs()
  33. {
  34. h=;t=;q[++t]=;dfn[t]=;//t=0,多组数据!
  35. while(h<=t)
  36. {
  37. int s=q[h],d=dfn[h++],i;
  38. for(i=;i<=n&&(s&(<<(i-)));i++);
  39. for(int j=i;j<=n;j++)
  40. {
  41. int x=(s|list[i][j]);if(vis[x])continue;//
  42. vis[x]=;q[++t]=x;dfn[t]=d+;
  43. if(x==lm-){printf("%d\n",dfn[t]);return;}
  44. }
  45. }
  46. }
  47. int main()
  48. {
  49. scanf("%d",&T);
  50. while(T--)
  51. {
  52. scanf("%d%d",&n,&tp);lm=(<<n);
  53. for(int i=;i<=n;i++)scanf("%lf%lf",&x[i],&y[i]);
  54. init();
  55. bfs();
  56. }
  57. return ;
  58. }

洛谷 2831 (NOIp2016) 愤怒的小鸟——仅+1所以bfs优化的更多相关文章

  1. 洛谷 1600 (NOIp2016) 天天爱跑步——树上差分

    题目:https://www.luogu.org/problemnew/show/P1600 看TJ:https://blog.csdn.net/clove_unique/article/detail ...

  2. BZOJ1563/洛谷P1912 诗人小G 【四边形不等式优化dp】

    题目链接 洛谷P1912[原题,需输出方案] BZOJ1563[无SPJ,只需输出结果] 题解 四边形不等式 什么是四边形不等式? 一个定义域在整数上的函数\(val(i,j)\),满足对\(\for ...

  3. 【题解】洛谷P1032 [NOIP2002TG]字串变换(BFS+字符串)

    洛谷P1032:https://www.luogu.org/problemnew/show/P1032 思路 初看题目觉得挺简单的一道题 但是仔细想了一下发现实现代码挺麻烦的 而且2002年的毒瘤输入 ...

  4. 洛谷P2216: [HAOI2007]理想的正方形 单调队列优化DP

    洛谷P2216 )逼着自己写DP 题意: 给定一个带有数字的矩阵,找出一个大小为n*n的矩阵,这个矩阵中最大值减最小值最小. 思路: 先处理出每一行每个格子到前面n个格子中的最大值和最小值.然后对每一 ...

  5. Luogu 2831 [NOIP2016] 愤怒的小鸟

    第一眼看成爆搜的状压dp,膜Chester大神犇. 考虑到三个不在同一直线上的点可以确定一条抛物线,而固定点$(0, 0)$和不在同一直线上这两个条件是题目中给定的,所以我们只要枚举两个点然后暴力算抛 ...

  6. 洛谷 1850 NOIP2016提高组 换教室

    [题解] 先用floyed处理出两点间的最短路. 设f[i][j][k]表示走到第i个教室,总共换了j次,当前换或者不换,期望的最小移动距离. 分情况讨论来转移即可. #include<cstd ...

  7. 洛谷P1850 [noip2016]换教室——期望DP

    题目:https://www.luogu.org/problemnew/show/P1850 注释掉了一堆愚蠢,自己还是太嫩了... 首先要注意选或不选是取 min 而不是 /2 ,因为这里的选或不选 ...

  8. 洛谷1850(NOIp2016) 换教室——期望dp

    题目:https://www.luogu.org/problemnew/show/P1850 状态里记录的是”上一回有没有申请“,而不是”上一回申请成功否“,不然“申请 j 次”就没法转移了. dou ...

  9. 洛谷P1563 [NOIP2016 提高组] 玩具谜题

    题目链接:https://www.luogu.com.cn/problem/P1563 哈哈哈,这个题拿来一读是不是很吃惊hahaha,我刚开始读的时候吓了我一跳,这么长的题干,这么绕的题意,还有下面 ...

随机推荐

  1. RBAC权限控制

    1.什么是RBAC权限模型rity2.RBAC权限模型表设计3.整合Mybatis数据库4.UserDetailsService5.动态查询数据库登陆6.动态权限角色拦截 什么是RBAC权限模型r 基 ...

  2. Mac 使用技巧分享

    1. 快捷键开启speech功能: System Preferences -> Ditaction&Speech ->Text to Speech ->Select 'Spe ...

  3. Java Swing窗体小工具实例 - 原创

    Java Swing窗体小工具实例 1.本地webserice发布,代码如下: 1.1 JdkWebService.java package server; import java.net.InetA ...

  4. JNIjw06

    1.VC6(CPP)的DLL代码: #include<stdio.h> #include "jniZ_JNIjw06.h" // 全局变量 jfieldID g_pro ...

  5. 一块网卡多个IP实现

    ////////////////////////////写在前面//////////////////////////////////////////// 需要注意,这里我们是一块网卡多个IP,而并非是 ...

  6. 【C#笔札】1 string类型

    C中没有string这个类型,而是用字符串数组来实现,相对来说比较麻烦. LABVIEW相对来说要简单太多,毕竟他主要的精力集中在硬件控制上,软件操作方面极其简单. C#类似,C#中有System.S ...

  7. saltstack技术入门与实践

    基本原理 SaltStack 采用`C/S`模式,server端就是salt的master,client端就是minion,minion与master之间通过`ZeroMQ`消息队列通信. minio ...

  8. 【spark】示例:二次排序

    我们有这样一个文件          首先我们的思路是把输入文件数据转化成键值对的形式进行比较不就好了嘛! 但是你要明白这一点,我们平时所使用的键值对是不具有比较意义的,也就说他们没法拿来直接比较. ...

  9. HTML——部分MP4在谷歌浏览器上无法播放

    Chrome浏览器支持HTML5,它支持原生播放部分的MP4格式(不用通过Flash等插件). 为什么是部分MP4呢?MP4有非常复杂的含义(见http://en.wikipedia.org/wiki ...

  10. display:inline-block 和 float 水平排列区别?

    文档流(Document flow):浮动元素会脱离文档流,并使得周围元素环绕这个元素.而inline-block元素仍在文档流内.因此设置inline-block不需要清除浮动.当然,周围元素不会环 ...