dfs

大一新生备战2020蓝桥杯

纵然是瞬间 提交于 2020-03-08 18:43:32
一:错误票据 关键字:排序 题目: 资源限制时间限制:1 .0s 内存限制:256.0MB问题描述 某涉密单位下发了某种票据,并要在年终全部收回。 每张票据有唯一的ID号。全年所有票据的ID号是连续的,但ID的开始数码是随机选定的。 因为工作人员疏忽,在录入ID号的时候发生了一处错误,造成了某个ID断号,另外一个ID重号。 你的任务是通过编程,找出断号的ID和重号的ID。 假设断号不可能发生在最大和最小号。 输入格式 要求程序首先输入一个整数N(N<100)表示后面数据行数。 接着读入N行数据。 每行数据长度不等,是用空格分开的若干个(不大于100个)正整数(不大于100000),请注意行内和行末可能有多余的空格,你的程序需要能处理这些空格。 每个整数代表一个ID号。 输出格式 要求程序输出1行,含两个整数m n,用空格分隔。 其中,m表示断号ID,n表示重号ID 样例输入1 2 5 6 8 11 9 10 12 9 样例输出1 7 9 样例输入2 6 164 178 108 109 180 155 141 159 104 182 179 118 137 184 115 124 125 129 168 196 172 189 127 107 112 192 103 131 133 169 158 128 102 110 148 139 157 140 195 197 185 152

POJ 3009 DFS

£可爱£侵袭症+ 提交于 2020-03-08 18:06:46
题面传送门 http://poj.org/problem?id=3009 要点:1.石头会停止于障碍物前或者终点处(即便终点后没有障碍物也会算成功) 2.石头扔出边界没有障碍物则会失败 3.扔石头次数超过10次会失败 开始用BFS写的代码,会超内存,因为要存储每一个状态下的地图。 以下附上DFS代码: #include <iostream> #include <cstdio> using namespace std; const int maxn = 25; int mapp[maxn][maxn]; int w[2]; //h w int dir[2] = {-1, 1}; int s[2];//起点 int e[2];//终点 int v;//最短路值 void DFS(int i, int j, int k) { if(k > 10) return ; //限制次数 if(i == e[0] && j == e[1]) { if (v == -1) v = k; else if(k < v) v = k; } else { int pos[2]; pos[0] = i; pos[1] = j; for(int x = 0; x < 2; x++) { for(int y = 0; y < 2; y++) { int d[2]; d[0] = pos[0]; d[1] =

leetcode 695 岛屿的最大面积

▼魔方 西西 提交于 2020-03-08 05:52:52
思路: 就是运用DFS深搜 先定义方向 然后定义dfs 递归函数,判断何时继续走,何时中止 然后在主函数循环遍历地图调用 dfs class Solution { int [][]direction = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}}; public int maxAreaOfIsland(int[][] grid) { int m = grid.length; int n = grid[0].length; int max = 0; for(int i =0; i < m; i ++) { for(int j = 0; j< n; j++) { max = Math.max(max, dfs(i, j,grid, direction, m , n)); } } return max ; } public int dfs(int r , int c , int[][] grid,int[][] direction, int m , int n) { if(r < 0|| c < 0 || r >= m || c >= n || grid[r][c] == 0) { return 0; } grid[r][c] = 0;//走过的点置为0 int area = 1; for(int []d :direction) { area += dfs(r

DFS spanning tree【贪心+树链剖分】

旧时模样 提交于 2020-03-08 03:01:13
题目链接 HDU - 4582 在开始解决这个问题之前,我们来解决如下一个问题: 有一段总长度为N的连续点集,现在给出M个区间段[Li, Ri]使得每个区间段中至少有一个点被染色,问最少需要染色多少个结点?(使用Nlog时间复杂度) 解:这个问题其实是一个贪心的过程,譬如说,我们先对R区间升序排序,然后呢,对于每个Li,我们只要知道它是否是在现在的已有的R区间包含内的,就可知道是否是需要新添加点的了。 回到这道题目上来, 题意 :有N个点构成的树,先给出N-1条树上的边,再给出M-N+1条我们需要查询的边,使得查询边与原树边构成的环上至少有一条边在树上。 那么,这问题岂不是跟之前提出的问题那么相像呢?就是所谓区间应该如何定义? 给出的M-N+1条“查询边”,我们可以定义为原树上的长链,于是乎,就是对这些长链进行之前的染色问题即可了,但是由于是在树上的,这时候应该如何等效过去呢? 首先,升序排序,我对于每条边的头结点进行按照深度的降序排列,保证了贪心的思路跟上是一样的,最深的是一定要取的。 其次,是查询了,怎么知道区间内的点是否被染色了?这里我很简单的使用了树链剖分来解决这个问题,虽然好像直接暴力搜也没有问题(好像,没试过),我用树链剖分来解决查询这个长链是否有边被染色过了,以及给边染色。 #include <iostream> #include <cstdio> #include

八皇后问题(dfs)

与世无争的帅哥 提交于 2020-03-08 02:43:25
八皇后问题,是一个古老而著名的问题,是搜索算法的经典案例。该问题是国际西洋棋棋手马克思贝瑟尔于1848年提出:在8*8格的国际象棋上摆放八个皇后。使其不能相互攻击,即任意两个皇后都不能处于同一行、同一列或者同一斜线,问有多少中摆法。 分析:用dfs一行一行得进行摆放,用for循环来确定每一列,由于是一行一行得摆放所以不可能同行,我们只需要标记同列,同对角线,就行,会发现主对角线一条对角线上的行列和等于同一个常数,副对角线一条对角线行列差等于一个常数,只不过会是负数,防止下标是负数我们可以进行+8,保证是一个正数,利用这个性质来确定有没有同行同列 # include <iostream> using namespace std ; bool v [ 10 ] , tx [ 20 ] , ty [ 20 ] ; //表示这一列,主对角线,负对角线有没有皇后 int cnt = 0 ; bool check ( int x , int y ) { return ! v [ y ] && ! tx [ x + y ] && ! ty [ x - y + 8 ] ; //+8防止产生负数 void dfs ( int x ) { if ( x == 8 ) { //找到了一种摆法 cnt ++ ; return ; } for ( int i = 0 ; i < 8 ; i ++ ) {

N皇后 · DFS

这一生的挚爱 提交于 2020-03-07 23:15:30
//本代码还未ac # include <bits/stdc++.h> using namespace std ; int n , m , K ; char mp [ 15 ] [ 15 ] ; int a [ 15 ] , b [ 15 ] , c [ 15 ] ; // 列 对角线 反对角线 // 列 a[i] // 对角线 y=-x+b b=y+x b[u+i] // 反对角线 y=x+b b=y-x+n c[i-u+n]多加了n是为了防止出现负数 void dfs ( int u ) { if ( u == n ) { for ( int i = 1 ; i <= n ; ++ i ) { puts ( mp [ i ] ) ; } puts ( "" ) ; return ; } for ( int i = 1 ; i <= n ; ++ i ) { if ( ! a [ i ] && ! b [ u + i ] && ! c [ n - u + i ] ) { mp [ u ] [ i ] = 'Q' ; a [ i ] = b [ u + i ] = c [ n - u + i ] = 1 ; dfs ( u + 1 ) ; a [ i ] = b [ u + i ] = c [ n - u + i ] = 1 ; mp [ u ] [ i ] = '.' ; } }

HDU 4582 DFS spanning tree

自作多情 提交于 2020-03-07 20:43:58
题意: 一张无向图中告诉你一个dfs树,还有若干反向边。问你如何选取最小的边使得所有只包含一条反向边的环被覆盖。 转化题意,一条不在生成树上的边能构成一个环,假设这条边是 \(u-v\) ,那么就可以看作在dfs生成树上的一条 \(u-v\) 的路径。要求在生成树上选最少的边使得能让每一条路径内都至少有一条选的边 这题有个特点,题目说了这些非树边都是反向边,那就说明了 \(u,v\) 的 lca 一定是 \(u,v\) 中的一个 我们这边设 \(u\) 的深度比 \(v\) 的深度小 很像线段覆盖问题,还记得我们线段覆盖怎么做的么,按照右端点排序,然后如果一条线段实在要放就一定要放在最边上 这题也类似,按照第一关键字 \(u\) 第二关键字 \(v\) 按照深度从深到浅排, 然后暴力模拟,如果从 \(v\) 开始一直往 \(u\) 暴力跳,如果路上的边都没被标记过,那么就肯定要选一个了,选 \(u\) 往 \(v\) 方向儿子的那条边,因为枚举顺序就是从深到浅,更深的路径已经被处理过了,所以要尽量放的浅一点 我的代码里标记路径是 \(vis[u]\) 表示 \(u\) 节点往父亲方向的边是否被标记 注意常数, 交之前洗把脸 // This code writed by chtholly_micromaker(MicroMaker) #include <bits/stdc++.h>

dfs-1 全排列

孤街醉人 提交于 2020-03-07 09:32:57
一个超简单的全排列问题 最近开始学习了一点dfs,做了一点水题..... 水题虽然是水题,但不做水题怎么做更难的题呢 说的还挺有道理 然后呢,就写一哈我的一点心得体会 #include<bits/stdc++.h> using namespace std; int a[10],b[10]={0},n; void dfs(int step){ int i; if(step==n+1){ for(i=1;i<=n;i++){ printf("%d ",a[i]); } printf("\n"); return; } for(i=1;i<=n;i++){ if(b[i]==0){ b[i]=1; a[step]=i; dfs(step+1); b[i]=0; } } return; } int main(){ scanf("%d",&n); dfs(1); return 0; } 代码我也已经弄出来了,对大佬们来说弱智的一批,但对于我这种蒟蒻来说还是有一丢丢难度的, 怎么说呢,算法的思想我其实是能理解的,但在具体的实现过程中我搞不懂为什么第一次排列出1 2 3,之后第二次会出现1 3 2,之后等等一些排列不同的数,然后我就debug了一下,终于发现了问题所在,这个排列的数字之所以每次都不一样是由这个for循环中的i来控制的,dfs函数从上一级跳出来之后,可能有的for循环还没有结束

ACM: HDU 2563 统计问题-DFS+打表

浪子不回头ぞ 提交于 2020-03-06 09:51:32
HDU 2563 统计问题 Time Limit: 1000MS Memory Limit: 32768KB 64bit IO Format: %I64d & %I64u HDU 2563 Description 在一无限大的二维平面中,我们做如下假设: 1、 每次只能移动一格; 2、 不能向后走(假设你的目的地是“向上”,那么你可以向左走,可以向右走,也可以向上走,但是不可以向下走); 3、 走过的格子立即塌陷无法再走第二次; 求走n步不同的方案数(2种走法只要有一步不一样,即被认为是不同的方案)。 Input 首先给出一个正整数C,表示有C组测试数据 接下来的C行,每行包含一个整数n (n<=20),表示要走n步。 Output 请编程输出走n步的不同方案总数; 每组的输出占一行。 Sample Input 2 1 2 Sample Output 3 7 /*/ 中文题,有点类似以前做过的小蜜蜂那题,规定一个方向后只能沿着三个方向去移动了。所以每次移动只有3种方向可以走,而且还要标记是否已经走过这条路,所以思路很清楚直接DFS。但是DFS会TLE,输入的数字在1~20,数据不多,直接打表。 AC代码: /*/ #include"map" #include"cmath" #include"string" #include"cstdio" #include"vector"

DFS入门

自作多情 提交于 2020-03-05 10:59:14
题目描述 排列与组合是常用的数学方法。 先给一个正整数 ( 1 < = n < = 10 ) 。例如n=3,所有组合,并且按字典序输出: 1 2 3 1 3 2 2 1 3 2 3 1 3 1 2 3 2 1 输入 输入一个整数n( 1<=n<=10) 输出 输出所有全排列 每个全排列一行,相邻两个数用空格隔开(最后一个数后面没有空格) 代码 global n num=[] vis=[] def DFS(x): if x==n: for i in range(n-1): print(str(num[i]),end=' ') print(num[n-1]) return for i in range(n): if vis[i]==0: vis[i]=1 num[x]=i+1 DFS(x+1) vis[i]=0 if __name__=="__main__": n=int(input()) vis=[0]*n num=[0]*n DFS(0) 题目描述 排列与组合是常用的数学方法,其中组合就是从n个元素中抽出r个元素(不分顺序且r < = n),我们可以简单地将n个元素理解为自然数1,2,…,n,从中任取r个数。 现要求你不用递归的方法输出所有组合。 例如n = 5 ,r = 3 ,所有组合为: 1 2 3 1 2 4 1 2 5 1 3 4 1 3 5 1 4 5 2 3 4 2 3