今天碰到了这样一道题目,是一个关于深搜的题目

4124:海贼王之伟大航路

  • 查看
  • 提交
  • 统计
  • 提示
  • 提问
总时间限制: 
1000ms 
内存限制: 
65536kB
描述

“我是要成为海贼王的男人!”,路飞一边喊着这样的口号,一边和他的伙伴们一起踏上了伟大航路的艰险历程。

路飞他们伟大航路行程的起点是罗格镇,终点是拉夫德鲁(那里藏匿着“唯一的大秘宝”——ONE PIECE)。而航程中间,则是各式各样的岛屿。

因为伟大航路上的气候十分异常,所以来往任意两个岛屿之间的时间差别很大,从A岛到B岛可能需要1天,而从B岛到A岛则可能需要1年。当然,任意两个岛之间的航行时间虽然差别很大,但都是已知的。

现在假设路飞一行从罗格镇(起点)出发,遍历伟大航路中间所有的岛屿(但是已经经过的岛屿不能再次经过),最后到达拉夫德鲁(终点)。假设他们在岛上不作任何的停留,请问,他们最少需要花费多少时间才能到达终点?

输入
输入数据包含多行。
第一行包含一个整数N(2 < N ≤ 16),代表伟大航路上一共有N个岛屿(包含起点的罗格镇和终点的拉夫德鲁)。其中,起点的编号为1,终点的编号为N。
之后的N行每一行包含N个整数,其中,第i(1 ≤ i ≤ N)行的第j(1 ≤ j ≤ N)个整数代表从第i个岛屿出发到第j个岛屿需要的时间t(0 < t < 10000)。第i行第i个整数为0。
输出
输出为一个整数,代表路飞一行从起点遍历所有中间岛屿(不重复)之后到达终点所需要的最少的时间。
样例输入
样例输入1:
4
0 10 20 999
5 0 90 30
99 50 0 10
999 1 2 0样例输入2:
5
0 18 13 98 8
89 0 45 78 43
22 38 0 96 12
68 19 29 0 52
95 83 21 24 0
样例输出
样例输出1:
100样例输出2:
137
提示
提示:
对于样例输入1:路飞选择从起点岛屿1出发,依次经过岛屿3,岛屿2,最后到达终点岛屿4。花费时间为20+50+30=100。
对于样例输入2:可能的路径及总时间为:
1,2,3,4,5: 18+45+96+52=211
1,2,4,3,5: 18+78+29+12=137
1,3,2,4,5: 13+38+78+52=181
1,3,4,2,5: 13+96+19+43=171
1,4,2,3,5: 98+19+45+12=174
1,4,3,2,5: 98+29+38+43=208
所以最短的时间花费为137
单纯的枚举在N=16时需要14!次运算,一定会超时。
这个乍一看是一个旅行商问题???但是后来仔细观察加网上查询发现通过深搜+剪枝就可以解决
这道题给我的启发是状态压缩
这道题里面的剪枝有两个
最基本的剪枝  当前得到的时间已经比之前所查询到的最短的时间要长了, 那么肯定不继续搜索了
比较复杂的剪枝, 当前的状态之前已经查询到了,而且之前到达当前状态的时候所花费的时间比当前花费的时间要少,那么也没有必要继续查询了 具体看一个数组 location_state[local_position][state] 
这里的local_position表示当前位于哪座城市 state则表示已经走了哪些城市
比如 5   1 2 3 5
5   3  1  2  5 这两种情况下 state都是一样的
这里state用位运算来表示 比如第一个城市走过了则把第一位变为1 所以第i个城市走过了  则有state+pow(2,i-1)来更新
具体可以看代码,这道题的另一个坑点在于必须要最后到达的城市是n,一开始我没注意这个条件,以为只要走过所有的城市就可以,最后错了
代码如下
// ConsoleApplication1.cpp : 定义控制台应用程序的入口点。
//#include "stdafx.h"
#include<iostream>
#include<cmath>
#include<stdio.h>
#include<memory.h>
using namespace std;
int n;
int cost[20][20];
int sum = 0;
int min_money;
bool vis[20];
int land_state[20][1 << 17];
int min1(int x, int y)
{return x < y ? x : y;
}
void dfs(int cur_land, int readycost, int state)
{sum++;  //城市+1vis[cur_land] = false; //标记当前城市if (sum == n - 1)  //如果只剩下一个城市了{min_money = min1(min_money, readycost + cost[cur_land][n]);  //求得min_moneyreturn;}if (readycost > min_money) return; //最简单的剪枝, 当前花费已经比结果多了,就不走了if (readycost < land_state[cur_land][state] || land_state[cur_land][state] == -1){land_state[cur_land][state] = readycost;}else return; //发现之前到达这个状态的时候结果比现在好,就剪掉for (int i = 1; i < n; i++){if (vis[i]){dfs(i, readycost + cost[cur_land][i], state + pow(2, i-1));vis[i] = true;sum--;}}
}int main()
{scanf("%d", &n);min_money = 1 << 30;memset(vis, true, sizeof(vis));memset(land_state, -1, sizeof(land_state));for (int i = 1; i <=n; i++)for (int j = 1; j <=n; j++)scanf("%d", &cost[i][j]);dfs(1, 0, 1);cout << min_money << endl;return 0;
}

DFS 简单的剪枝和状态压缩 海贼王之伟大航路相关推荐

  1. 状态压缩技巧:动态规划的降维打击

    刷题认准labuladong 东哥带你手把手撕力扣???? 点击下方卡片即可搜索???? 我们号之前写过十几篇动态规划文章,可以说动态规划技巧对于算法效率的提升非常可观,一般来说都能把指数级和阶乘级时 ...

  2. POJ2688状态压缩(可以+DFS剪枝)

    题意:       给你一个n*m的格子,然后给你一个起点,让你遍历所有的垃圾,就是终点不唯一,问你最小路径是多少? 思路:       水题,方法比较多,最省事的就是直接就一个BFS状态压缩暴搜就行 ...

  3. LeetCode 1723. 完成所有工作的最短时间(DFS+剪枝 / 状态压缩DP)

    文章目录 1. 题目 2. 解题 2.1 DFS 2.2 状态压缩DP 265 / 3871, 前6.85% 前3题题解: LeetCode 5649. 解码异或后的数组(位运算) LeetCode ...

  4. 状态压缩+dfs+背包

    状态压缩dp 状态压缩dp就是用二进制数字来表示状态,通过遍历所有状态确定答案,时间复杂度为o(nn2^n),通常只能用来解数据范围小于等于21的. P1433 吃奶酪 #include <bi ...

  5. uva10160(dfs+状态压缩)

    题意:给出n个点,以及m条边,这些边代表着这些点相连,修一个电力站,若在某一点修一个站,那么与这个点相连的点都可以通电,问所有的点都通电的话至少要修多少个电力站........ 思路:最多给出的是35 ...

  6. 洛谷P1562 还是N皇后(DFS+状态压缩+位运算)

    八皇后问题的介绍在此不再赘述,只贴一下经典八皇后问题的实现代码(参考刘汝佳 <算法竞赛入门经典>) void search(int i) {if(i>n){ans++;return; ...

  7. 《算法竞赛进阶指南》打卡-基本算法-AcWing 94. 递归实现排列型枚举:dfs、二进制状态压缩

    文章目录 题目解答 题目来源 题目解答 分析: dfs求全排列,这里是用二进制状态压缩进行优化,二进制状态压缩,顾名思义,每个状态是用二进制的某一位表示.这里的体现是state这个状态,它的每一位代表 ...

  8. 《算法竞赛进阶指南》打卡-基本算法-AcWing 93. 递归实现组合型枚举:递归与递推、dfs、状态压缩

    文章目录 题目解答 题目链接 题目解答 分析: 此题和笔者另一篇博文很像,只不过是限定了个数.<算法竞赛进阶指南>打卡-基本算法-AcWing 92. 递归实现指数型枚举:递推与递归.二进 ...

  9. 《算法竞赛进阶指南》打卡-基本算法-AcWing 92. 递归实现指数型枚举:递推与递归、二进制状态压缩、dfs

    文章目录 题目解答 题目链接 题目解答 分析: 优化:用二进制状态压缩,也就是用二进制上的位来记录数有没有被用过. ac代码 #include<bits/stdc++.h> using n ...

最新文章

  1. SFB 项目经验-13-为某上市企业仅安装Skype for Business 2016(图解)
  2. java中懒汉饿汉编写及比较
  3. 算法 --- 递归实现多级树展开结构
  4. java社区活跃度_Java并发编程-活跃度问题
  5. 计算机选配 注意事项,选择鼠标注意事项有哪些
  6. golang游戏服务器框架_Go开源游戏服务器框架——Pitaya
  7. 无锡金秋购物节 淘菜菜提供社区消费全景式服务
  8. Jenkins学习总结(5)——免费DevOps开源工具简介
  9. python画简便的图-python 实现在一张图中绘制一个小的子图方法
  10. 从支付宝SDK的支付流程理解什么是公钥和私钥,什么是加密和数字签名
  11. 字符串lcfirst解析
  12. 数据结构之红黑树简介
  13. 数字信号处理常见知识点汇总
  14. LeetCode-1225. 报告系统状态的连续日期(困难)
  15. python网络安全怎么学_新手如何学习网络安全?
  16. excel----身份证号校验位excel公式分析
  17. m.444lu.co show.php,vml圆角矩形最简布局_javascript技巧
  18. 数组按数字出现频次排序
  19. linux如何进conf模式,Linux 中 vi /etc/sysctl.conf 如何编辑
  20. 关于rx,tx或I2C串口不够的问题

热门文章

  1. Nginx葵花宝典—草根站长Nginx运维百科全书
  2. python右键idel消失问题
  3. 关于word页眉页脚的设置-页码不连续的问题
  4. SQLite查询记录总数
  5. C语言三个整蛊程序,很强!!
  6. python抽取某个时间段的数据_python 批量提取excel 指定时间段的数据
  7. 字符串函数 tirm 的作用
  8. Adobe Lightroom Classic 入门教程(七)修改照片 --- 暗角颗粒与相机配置校正
  9. 刺客信条奥德赛多项功能修改器(附游戏攻略)
  10. 音视频传输-之RTP/RTCP协议