dfs

图的实现(邻接矩阵)及DFS、BFS

倖福魔咒の 提交于 2020-02-10 00:45:02
@author QYX 写作时间:2013/0302 最近准备noi比赛,加油!!! 因为近期学习任务太多太紧,所以我主要维护Github,博客园可能会停更几天。----2020年2月9日 图 图(graph)是用线连接在一起的顶点或节点的集合,即两个要素:边和顶点。每一条边连接个两个顶点,用(i,j)表示顶点为 i 和 j 的边。 ​ 如果用图示来表示一个图,一般用圆圈表示顶点,线段表示边。有方向的边称为有向边,对应的图成为有向图,没有方向的边称为无向边,对应的图叫无向图。对于无向图,边(i, j)和(j,i)是一样的,称顶点 i 和 j 是邻接的,边(i,j)关联于顶点 i 和 j ;对于有向图,边(i,j)表示由顶点 i 指向顶点 j 的边,即称顶点 i 邻接至顶点 j ,顶点 i 邻接于顶点 j ,边(i,j)关联至顶点 j 而关联于顶点 i 。 ​ 对于很多的实际问题,不同顶点之间的边的权值(长度、重量、成本、价值等实际意义)是不一样的,所以这样的图被称为加权图,反之边没有权值的图称为无权图。所以,图分为四种:加权有向图,加权无向图,无权有向图,无权无向图。 图的表现有很多种,邻接表法,临接矩阵等。 图经常是以这种形式出现的[weight,from,to]的n*3维数组出现的,见名知意,三个元素分别为边的权重,从哪儿来,到哪儿去。 如上图所示,由一条边连接在一起的顶点称为

【DFS】置棋问题

对着背影说爱祢 提交于 2020-02-09 18:20:25
题目描述 在M*N的主格中任意指定X个格子构成一个棋盘,而其它格子是残缺的,不能放棋子。在任一个构成的棋盘上放置K个棋子,要求任意两个棋子不得位于同一行或同一列上。求满足条件的所有方案数。 注意:棋盘是稀疏的,即X<(M*N)/2 输入: 第1行:2个整数M,N,表示棋盘的行数和列数( 1<M,N<10) 接下来是M行,每行N个空格分开的数字(0或者1),1表示相应的格子在棋盘上,0表示相应的格子不在棋盘上。 输出: 第1行:1个整数表示可放置的最多的棋子数P 接下来P行,每行分别列出放i(1≤i≤P)个棋子时的方案总数。 样例输入1: 5 4 0 1 1 1 0 1 0 0 1 1 1 0 0 0 1 0 0 0 1 1 样例输出1: 4 1:10 2:28 3:24 4:5 思路: 题目中提到两个棋子不能同行或者同列,基本可以判定为8皇后的问题了,而且还稍稍简单一些,没有对角线的问题。dfs函数两个参数,一个是行,一个是当前置了几个棋子了,行数超过棋盘行数就是停止条件。稍微不同的地方是答案的记录方式,这里用一个数组来记录, ans[step]++; 即step个棋子的方法数自增。 代码的框架也可以确定了,按行搜索,每行按列标记。 代码 # include <bits/stdc++.h> using namespace std ; int n , m ; int mp [ 15

LC 1349. Maximum Students Taking Exam

蓝咒 提交于 2020-02-09 16:30:31
Link Solution 0: class Solution { public: int m,n; int maxStudents(vector<vector<char>>& seats) { m=seats.size(); n=seats[0].size(); vector<vector<int>> dp(m*n+2,vector<int>(1<<(2*n),-1)); return dfs(seats,0,0,dp); } int dfs(vector<vector<char>>& seats, int pos, int state, vector<vector<int>> &dp){ if(dp[pos][state]!=-1) return dp[pos][state]; if(pos==m*n) return 0; int x=pos/n; int y=pos%n; if(y==0){ state=state>>n; } int take=0,untake=0; untake=dfs(seats,pos+1,state,dp); int flag=0; if(seats[x][y]=='#') flag=1; if(y-1>=0 && (state&(1<<(y-1+n)))>0) flag=1; if(y+1<n && (state&(1<<(y+1+n)))>0)

Werewolf

╄→гoц情女王★ 提交于 2020-02-09 01:28:02
Werewolf(狼人杀) is a game in which the players are partitioned into two parties: the werewolves and the human beings. Suppose that in a game, player #1 said: "Player #2 is a werewolf."; player #2 said: "Player #3 is a human."; player #3 said: "Player #4 is a werewolf."; player #4 said: "Player #5 is a human."; and player #5 said: "Player #4 is a human.". Given that there were 2 werewolves among them, at least one but not all the werewolves were lying, and there were exactly 2 liars. Can you point out the werewolves? Now you are asked to solve a harder vertion of this problem: given that there

P1057传球游戏

时光总嘲笑我的痴心妄想 提交于 2020-02-08 20:30:57
P1057传球游戏 1.题意 见链接 2.分析 这题需要使用手动简单的模拟一下,原题中的一个测试用例便是一个好的例子,传球只能往左边或右边传,相应的,传球次数减一,我们深搜这个状态直到最终传到第一个人手里。于是得到深搜的主要过程: f[i][j] = dfs( (i+1)%n,j-1 ) + dfs( (i-1 + n)%n,j-1 ); 。其中 f[i][j] 代表的是 经过 j 次传球回到i号人手中 3.代码 第一次提交的代码如下: # include <iostream> # include <cstdio> using namespace std ; const int maxN = 35 ; int n , m ; int f [ maxN ] [ maxN ] ; //f[i][j] 用于计算"经过j次传球回到i号人手中" //计算"经过j次传球回到i号人手中" int dfs ( int i , int j ) { //我也是因为“根据是否是0决定是否返回“导致TLE. if ( f [ i ] [ j ] != - 1 ) return f [ i ] [ j ] ; if ( j == 0 && i != 0 ) return 0 ; //printf("i = %d,j= %d\n",i,j); //计算值 //1.(i-1+n)%n f [ i ] [ j ]

DFS求解水洼数目(java版)

浪子不回头ぞ 提交于 2020-02-08 12:19:22
题目描述 有一个大小为 N * M 的园子,雨后积起了水。八连通的积水被认为是连接在一起的。请求出 园子里总共有多少水洼?(八连通指的是下图中相对 W 的*的部分) *** *W* *** 限制条件 N, M ≤ 100 样例: 输入 N=10, M=12 园子如下图('W’表示积水, '.'表示没有积水) 输出 3 思路分析 这道题目很经典,值得以后多去研究研究。问题是要我们求解出连着的一片的水洼的数量,对于这类经典的问题,使用其它迭代等的方法是难以求解的,因为我们不知道连着的积水的区域有多少,对于这类问题的求解,我们是采用常用的无死角搜索的深度优先搜索dfs算法来解决,因为dfs能够帮助我们搜索出所有的可能,尝试去走每一条路线,直到所有的路线都被走完了,那么dfs就终止了。 其中涉及到搜索以自己为中心的八个方向的搜索,所以存在着八个平行状态的搜索,这里使用到了一个技巧就是使用两层的for循环来进行处理。 这里还有一个技巧 就是当发现这个位置有积水的时候就把这个位置变为干燥,这样在往下搜索的过程中就能避免往上搜索而造成递归无法出去的问题。这样当一个dfs搜索完之后那么它周围的积水都被清除掉了,那么继续寻找下一个有积水的地方然后进行dfs,当所有的积水区域都被干燥之后那么水洼的数量就计算出来了。 代码实现 package LanQiao ; import java . util .

CF1276B B. Two Fairs 1900 (图上做dfs ,简单题)

爷,独闯天下 提交于 2020-02-08 05:41:50
图上做dfs() 本题链接 题意: 给一张 连通 的 无向 图,同时给你两个重要点,询问图上有多少对点满足从一个点到另一个点都必须经过这两个重要点。 思路: 本题的答案应该就是只有b能到的点*只有a能到的点,因为图连通,一个小技巧,dfs时直接将a点标记走过,dfs(b)点,标记为0的点就是只有a点能到的点,dfs(a)亦然,快速秒杀这道题。 # include <bits/stdc++.h> # define pb push_back using namespace std ; const int N = 200020 ; 来源: CSDN 作者: 路明非hero 链接: https://blog.csdn.net/qq_44767279/article/details/104210666

机试刷题:PAT A 1091 Acute Stroke 的BFS和DFS方法解析

筅森魡賤 提交于 2020-02-07 12:23:21
目录 PAT A 1091 Acute Stroke 题目 题目分析 bfs ~~dfs~~ dfs PAT A 1091 Acute Stroke 题目 One important factor to identify acute stroke (急性脑卒中) is the volume of the stroke core. Given the results of image analysis in which the core regions are identified in each MRI slice, your job is to calculate the volume of the stroke core. Input Specification: Each input file contains one test case. For each case, the first line contains 4 positive integers: M, N, L and T, where M and N are the sizes of each slice (i.e. pixels of a slice are in an M×N matrix, and the maximum resolution is 1286 by 128); L (≤60) is the

搜索专题总结

早过忘川 提交于 2020-02-07 06:55:21
搜索专题总结 第七章的例题做得差不多了,还有一道枚举二叉树和一道比较难的搜方块的没过,另外有一道火柴的用IDA*水过,并没有过大数据,由于这道可以用dancing links过,所以留着dancing links一坑。接下来总结下这章的收获,首先最重要的当然是不需要判重的高效率的IDA*以及估价函数的设计技巧;然后是bfs+hash写得更熟练了,如果hash需要erase那么就只能用指针版的,但是效率会很慢,否则就用数组版的。 做搜索题的几个要点: 1,估算最坏复杂度。 2,寻找合适的剪枝策略,估计剪枝的效果,根据情况选择IDA*还是bfs,最坏复杂度高但剪枝效果明显的优先IDA*。 3,想清楚代码的大致框架。 4,想清楚代码实现困难的细节以及可能出错需要注意的地方。 5,大胆快速的写吧。 下面是第七章的例题: A题: 输出所有的 xxxxx / xxxxx = N 只要枚举上面的数字就行了,复杂度<10^5,直接循环枚举。 #include<bits/stdc++.h> #define REP(i,a,b) for(int i=a;i<=b;i++) #define MS0(a) memset(a,0,sizeof(a)) #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 using namespace std; typedef

hdu入门搜索题

痴心易碎 提交于 2020-02-07 06:09:09
新人们加油,就优先队列有点难度,其它对新手很有学习价值 下面是我今晚刚刚刷的几道基本搜索题 hdu 1010 Tempter of the Bone 经典搜索入门题,DFS,本题考查要点:剪枝,奇偶性剪枝 View Code #include<stdio.h> #include<stdlib.h> int m,n,t; char map[8][8]; int dir[4][2]={{1,0},{-1,0},{0,-1},{0,1}}; int ex,ey,sx,sy,ok;//e表示end,终点,s表示start,出发点,ok用来判断是否在规定时间到达 void dfs(int x,int y,int cnt) { int i; if(cnt==t)//剪枝1:到时间了符合条件ok=1再退出,不符合条件直接退出。 { if(ex==x&&ey==y)ok=1; return; } if(ok)return;//找到解后还有部分在继续搜索,这条是为了让其它搜索停止 int temp=abs(x-ex)+abs(y-ey)-abs(cnt-t);//剪枝2:((((要点)))) //奇偶性剪枝 ,起点和终点确定以后就可以确定走的步数是奇数还是偶数,通过这个特点来剪枝 if(temp>0||temp&1)return;//temp&1相当于temp%2,运算位。 for(i=0;i<4