这道题目如果数据很小的话。我们通过这个dfs就可以完成深搜:


  1. void dfs(int s)
  2. {
  3. if (s==N)
  4. {
  5. minLen=min(minLen,totalLen);
  6. return ;
  7. }
  8. for (int i=0;i<G[s].size();i++)
  9. {
  10. Road r=G[s][i];
  11. if (r.t+totalCost>K)
  12. continue;
  13. if (!visited[r.d])
  14. {
  15. visited[r.d]=1;
  16. totalLen+=r.L;
  17. totalCost+=r.t;
  18. dfs(r.d);
  19. totalCost-=r.t;
  20. totalLen-=r.L;
  21. visited[r.d]=0;
  22. }
  23. }
  24. }

我们可以看一下这个代码,意思就是说,如果找边的时候,我们已经搜索到了终点,也就是s==N的时候,我们就直接改写minLen,然后返回到上一层,进行totalCost,totalLen和visited数组的返回工作,因为我们这次走的是这一条路,当我们返回的时候,就将这条路的终点标记全部还原,因为从这条路的起始点还可能会有其它的路,如果不把它还原的话,其它的路就被封死了,深搜就无法进行的很完全了,不能说是遍历了。

我们对于以s为起点的边进行遍历,发现边r的花费加上之前的总花销已经超过K,总钱数了,我们就跳过这一条边,这是第一次剪枝。

如果我们没有访问过边r的终点d时,我们就把它访问位设置为1,总路程加上r边长,总花费加上r边的过路费,然后深搜d。

这是可以通过一些较小的数据的,但是这道题中的数据很大,而dfs中又做了很多的无用功,所以我们进行以下的剪枝:

如果d点没有被访问过,我们就判断如果这次走到点d的时候,总路程已经超过minLen了,也就是之前找到的最短路,我们就跳过这个终点的深搜,我们直接不走这条路了。

这个剪枝还是不够,所以我们拿空间换取时间,我们设置一个minL[110][10010]数组,minL[k][m]表示之前走到点k并且花费为m的最短长度。

如果我们这次走到点k,并且花销为m,但是我们的路程已经大于这个最短长度了,我们就跳出这重循环,执行循环的下一次。

因为它的意思,也就是说,我们每走过一个点,我们就进行一次比较,确保我们不花相同的钱,走更远的路,这个剪枝极为有效,直接可以过。

代码如下:

  1. #include <iostream>
  2. #include <vector>
  3. #include <cstring>
  4. using namespace std;
  5. int N,K,R;
  6. struct Road {
  7. int d,L,t;
  8. };
  9. vector < vector<Road> > G(110);
  10. int minLen;
  11. int minL[110][10010];
  12. int totalLen;
  13. int totalCost;
  14. int visited[110];
  15. void dfs(int s)
  16. {
  17. if (s==N)
  18. {
  19. minLen=min(minLen,totalLen);
  20. return ;
  21. }
  22. for (int i=0;i<G[s].size();i++)
  23. {
  24. Road r=G[s][i];
  25. if (r.t+totalCost>K)
  26. continue;
  27. if (!visited[r.d])
  28. {
  29. if (totalLen+r.L>=minLen)
  30. continue;
  31. if (totalLen+r.L>=minL[r.d][r.t+totalCost])
  32. continue;
  33. visited[r.d]=1;
  34. totalLen+=r.L;
  35. minL[r.d][r.t+totalCost]=totalLen;
  36. totalCost+=r.t;
  37. dfs(r.d);
  38. totalCost-=r.t;
  39. totalLen-=r.L;
  40. visited[r.d]=0;
  41. }
  42. }
  43. }
  44. int main()
  45. {
  46. cin>>K>>N>>R;
  47. for (int i=0;i<R;i++) {
  48. int s;
  49. Road r;
  50. cin>>s>>r.d>>r.L>>r.t;
  51. if (s!=r.d) {
  52. G[s].push_back(r);
  53. }
  54. }
  55. memset(visited,0,sizeof(visited));
  56. for (int i=0;i<110;i++) {
  57. for (int j=0;j<10010;j++) {
  58. minL[i][j]=1<<30;
  59. }
  60. }
  61. totalLen=0;
  62. totalCost=0;
  63. minLen=1<<30;
  64. visited[1]=1;
  65. dfs(1);
  66. if (minLen<(1<<30))
  67. cout<<minLen<<endl;
  68. else cout<<-1<<endl;
  69. return 0;
  70. }

POJ-1724 深搜剪枝的更多相关文章

  1. POJ 2531 深搜剪枝

    题意:全局最大割. 分析:有相应的算法,数据量很小,可以枚举源点,汇点,最大流. 这里用DFS,状态定义:分成两个集合,刚开始S集合全部点,然后一个一个放,这是一个回溯的过程. 没剪枝也过了. 剪枝技 ...

  2. Hdu3812-Sea Sky(深搜+剪枝)

    Sea and Sky are the most favorite things of iSea, even when he was a small child.  Suzi once wrote: ...

  3. 深搜+剪枝 POJ 1724 ROADS

    POJ 1724 ROADS Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 12766   Accepted: 4722 D ...

  4. poj1190 生日蛋糕(深搜+剪枝)

    题目链接:poj1190 生日蛋糕 解题思路: 深搜,枚举:每一层可能的高度和半径 确定搜索范围:底层蛋糕的最大可能半径和最大可能高度 搜索顺序:从底层往上搭蛋糕,在同一层尝试时,半径和高度都是从大到 ...

  5. UVA 10160 Servicing Stations(深搜 + 剪枝)

    Problem D: Servicing stations A company offers personal computers for sale in N towns (3 <= N < ...

  6. ACM 海贼王之伟大航路(深搜剪枝)

    "我是要成为海贼王的男人!" 路飞他们伟大航路行程的起点是罗格镇,终点是拉夫德鲁(那里藏匿着"唯一的大秘宝"--ONE PIECE).而航程中间,则是各式各样的 ...

  7. hdu 1518 Square(深搜+剪枝)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1518 题目大意:根据题目所给的几条边,来判断是否能构成正方形,一个很好的深搜应用,注意剪枝,以防超时! ...

  8. 一本通例题-生日蛋糕——题解<超强深搜剪枝,从无限到有限>

    题目传送 显然是道深搜题.由于蛋糕上表面在最底层的半径确认后就确认了,所以搜索时的面积着重看侧面积. 找维度/搜索面临状态/对象:当前体积v,当前外表面面积s,各层的半径r[],各层的高度h[]. 可 ...

  9. 模拟赛T5 : domino ——深搜+剪枝+位运算优化

    这道题涉及的知识点有点多... 所以还是比较有意思的. domino 描述 迈克生日那天收到一张 N*N 的表格(1 ≤ N ≤ 2000),每个格子里有一个非 负整数(整数范围 0~1000),迈克 ...

随机推荐

  1. 介绍一下Extern “C”,它的作用是什么?

    Extern “C”是由C++提供的一个连接交换指定符号,用于告诉C++这段代码是C函数.这是因为C++编译后库中函数名会变得很长,与C生成的不一致,造成C++不能直接调用C函数,加上extren “ ...

  2. bzoj 3109: [cqoi2013]新数独【dfs】

    按3x3的小块dfs,填数的时候直接满足所有条件即可 #include<iostream> #include<cstdio> #include<cstring> u ...

  3. thinkphp5升级版开源框架tpframe v2.1发布

    免费开源框架tpframe是一款以thinkphp5为驱动,在此基础上进行进一步的完善与改进的框架,保持了ThinkPHP5原有的所有特性,优化核心,减少依赖,为个人或企业建站提供高效.快速解决的方案 ...

  4. 第二篇 .NET高级技术之密闭类和静态类及扩展方法

    1.密闭类是修饰为sealed的类, sealed不能有子类.一般只有系统中的一些基本类声明为sealed.面试题:是否可以编写一个类继承自String类? 答:不能,因为string被声明为了sea ...

  5. vs2010中的ADO控件及绑定控件

    要在项目中添加某一个ActiveX控件,则该ActiveX控件必须要注册.由于VS2010中,并没有自动注册ADO及ADO数据绑定控件(Microsoft ADO Data Control,Micro ...

  6. nginx memcache缓存

    1 基本 在一个lnmp架构中,nginx遇到动态资源,会反向代理,把请求发送到后端的php-fpm服务,php-fpm从mysql里读取数据,生产网页,然后返回给client. 如果流量大,php- ...

  7. bzoj2154||洛谷P1829 Crash的数字表格&&JZPTAB && bzoj3309 DZY Loves Math

    bzoj2154||洛谷P1829 https://www.lydsy.com/JudgeOnline/problem.php?id=2154 https://www.luogu.org/proble ...

  8. .net excel 导入 导出

    哎,好好的代码今天说来个实验,结果用的是office15 气死人了,网上最高office14.dll 文章转自2012年 QQ群:13615607 MR.Young protected void Bt ...

  9. java设计模式之单例设计模式

    单例设计模式 保证一个类在使用过程中,只有一个实例.优势就是他的作用,这个类永远只有一个实例. 优势:这个类永远只有一个实例,占用内存少,有利于Java垃圾回收. 单例设计模式关键点 私有的构造方法. ...

  10. 自定义 TypeHandler

    自定义TypeHandler分为三个步骤: 1.编写自定义TypeHandler,并继承自抽象类BaseTypeHandler<T>,实现抽象方法 2.在mybatis-config.xm ...