DFS 简单的剪枝和状态压缩 海贼王之伟大航路
今天碰到了这样一道题目,是一个关于深搜的题目
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 简单的剪枝和状态压缩 海贼王之伟大航路相关推荐
- 状态压缩技巧:动态规划的降维打击
刷题认准labuladong 东哥带你手把手撕力扣???? 点击下方卡片即可搜索???? 我们号之前写过十几篇动态规划文章,可以说动态规划技巧对于算法效率的提升非常可观,一般来说都能把指数级和阶乘级时 ...
- POJ2688状态压缩(可以+DFS剪枝)
题意: 给你一个n*m的格子,然后给你一个起点,让你遍历所有的垃圾,就是终点不唯一,问你最小路径是多少? 思路: 水题,方法比较多,最省事的就是直接就一个BFS状态压缩暴搜就行 ...
- LeetCode 1723. 完成所有工作的最短时间(DFS+剪枝 / 状态压缩DP)
文章目录 1. 题目 2. 解题 2.1 DFS 2.2 状态压缩DP 265 / 3871, 前6.85% 前3题题解: LeetCode 5649. 解码异或后的数组(位运算) LeetCode ...
- 状态压缩+dfs+背包
状态压缩dp 状态压缩dp就是用二进制数字来表示状态,通过遍历所有状态确定答案,时间复杂度为o(nn2^n),通常只能用来解数据范围小于等于21的. P1433 吃奶酪 #include <bi ...
- uva10160(dfs+状态压缩)
题意:给出n个点,以及m条边,这些边代表着这些点相连,修一个电力站,若在某一点修一个站,那么与这个点相连的点都可以通电,问所有的点都通电的话至少要修多少个电力站........ 思路:最多给出的是35 ...
- 洛谷P1562 还是N皇后(DFS+状态压缩+位运算)
八皇后问题的介绍在此不再赘述,只贴一下经典八皇后问题的实现代码(参考刘汝佳 <算法竞赛入门经典>) void search(int i) {if(i>n){ans++;return; ...
- 《算法竞赛进阶指南》打卡-基本算法-AcWing 94. 递归实现排列型枚举:dfs、二进制状态压缩
文章目录 题目解答 题目来源 题目解答 分析: dfs求全排列,这里是用二进制状态压缩进行优化,二进制状态压缩,顾名思义,每个状态是用二进制的某一位表示.这里的体现是state这个状态,它的每一位代表 ...
- 《算法竞赛进阶指南》打卡-基本算法-AcWing 93. 递归实现组合型枚举:递归与递推、dfs、状态压缩
文章目录 题目解答 题目链接 题目解答 分析: 此题和笔者另一篇博文很像,只不过是限定了个数.<算法竞赛进阶指南>打卡-基本算法-AcWing 92. 递归实现指数型枚举:递推与递归.二进 ...
- 《算法竞赛进阶指南》打卡-基本算法-AcWing 92. 递归实现指数型枚举:递推与递归、二进制状态压缩、dfs
文章目录 题目解答 题目链接 题目解答 分析: 优化:用二进制状态压缩,也就是用二进制上的位来记录数有没有被用过. ac代码 #include<bits/stdc++.h> using n ...
最新文章
- SFB 项目经验-13-为某上市企业仅安装Skype for Business 2016(图解)
- java中懒汉饿汉编写及比较
- 算法 --- 递归实现多级树展开结构
- java社区活跃度_Java并发编程-活跃度问题
- 计算机选配 注意事项,选择鼠标注意事项有哪些
- golang游戏服务器框架_Go开源游戏服务器框架——Pitaya
- 无锡金秋购物节 淘菜菜提供社区消费全景式服务
- Jenkins学习总结(5)——免费DevOps开源工具简介
- python画简便的图-python 实现在一张图中绘制一个小的子图方法
- 从支付宝SDK的支付流程理解什么是公钥和私钥,什么是加密和数字签名
- 字符串lcfirst解析
- 数据结构之红黑树简介
- 数字信号处理常见知识点汇总
- LeetCode-1225. 报告系统状态的连续日期(困难)
- python网络安全怎么学_新手如何学习网络安全?
- excel----身份证号校验位excel公式分析
- m.444lu.co show.php,vml圆角矩形最简布局_javascript技巧
- 数组按数字出现频次排序
- linux如何进conf模式,Linux 中 vi /etc/sysctl.conf 如何编辑
- 关于rx,tx或I2C串口不够的问题