dfs

7月、8月考试总结(1)

霸气de小男生 提交于 2020-02-07 04:53:22
7.10 : Test1 惨遭爆零 TAT    第一题 在本地测是过了的 到了教师机莫名输出0 ?? 一道spfa的板子题 还做过 WA了也就GG。。 [POJ2502]Subway    后来发现了 结构体强转有大问题???? woc    第二题 听大佬讲 有三种方法   1是floyd判一下 f[x][y] ?= f[x][k] + f[k][y] 还标记个flag(是否存在);   2是一个spfa找负环 这需要建一个神奇的图;   3是一个诡异的贪心 (左端相等 减去左边相等的数 再加入优先队列 如果区间相等 判断数是否相等 不相等就false)。   反正我都没想到 (难道高斯消元+区间离散 不能做?? 到时候再研究) 洛谷【P2294】[HNOI2005]狡猾的商人  后来点开标签看了看 原来是差分约束(虽然原来好像讲过,但根本不记得了) 去网上找了篇 好博文 终于懂了    第三题 一道强联通分量缩点 + 树形(DAG)dp 没时间写了 也只好GG 洛谷【P3436】[POI2006]PRO-Professor Szu    总结:先做思路更明显的题 程序注意细节 不要瞎搞 再接再厉 明天继续 fighting 7.12: Test2 130分。。(一般人拿的分qwq)    第一题 一道求解涂色方案数问题 判是否可行 看到就一脸懵 以为又是一道数学找规律题

P1164 小A点菜(C++_(DP)/(DFS+剪枝))

*爱你&永不变心* 提交于 2020-02-06 03:36:35
题目背景 uim神犇拿到了uoi的ra(镭牌)后,立刻拉着基友小A到了一家……餐馆,很低端的那种。 uim指着墙上的价目表(太低级了没有菜单),说:“随便点”。 题目描述 不过uim由于买了一些辅(e)辅(ro)书,口袋里只剩M元(M≤10000)。 餐馆虽低端,但是菜品种类不少,有N种(N≤100),第i种卖ai元(ai≤1000)。由于是很低端的餐馆,所以每种菜只有一份。 小A奉行“不把钱吃光不罢休”,所以他点单一定刚好吧uim身上所有钱花完。他想知道有多少种点菜方法。 由于小A肚子太饿,所以最多只能等待1秒。 输入格式 第一行是两个数字,表示N和M。 第二行起N个正数ai(可以有相同的数字,每个数字均在1000以内)。 输出格式 一个正整数,表示点菜方案数,保证答案的范围在int之内。 输入输出样例 输入 #1 4 4 1 1 2 2 输出 #1 3 思路 这道题其实我是直接用dfs+剪枝A掉的,后来又用01背包的dp板子再A了一遍… 源码 DP解法: # include <bits/stdc++.h> using namespace std ; int main ( ) { int n , m , v [ 110 ] , dp [ 10010 ] ; cin >> n >> m ; //n种食材, 共有m元 memset ( dp , 0 , sizeof ( dp ) )

二分图 最大权匹配 km算法

瘦欲@ 提交于 2020-02-06 02:48:15
这个算法的本质还是不断的找增广路; KM算法的正确性基于以下定理: 若由二分图中所有满足A[i]+B[j]=w[i,j]的边(i,j)构成的子图(称做相等子图)有完备匹配,那么这个完备匹配就是二分图的最大权匹配。 这个定理是显然的。因为对于二分图的任意一个匹配,如果它包含于相等子图,那么它的边权和等于所有顶点的顶标和;如果它有的边不包含于相等子图,那么它的边权和小于所有顶点的顶标和。所以相等子图的完备匹配一定是二分图的最大权匹配。 (1)可行点标:每个点有一个标号,记lx[i]为X方点i的标号,ly[j]为Y方点j的标号。如果对于图中的任意边(i, j, W)都有lx[i]+ly[j]>=W,则这一组点标是 可行 的。特别地,对于lx[i]+ly[j]=W的边(i, j, W),称为 可行边 ; (2)KM算法的核心思想就是通过修改某些点的标号(但要满足点标始终是可行的),不断增加图中的可行边总数,直到图中存在仅由可行边组成的完全匹配为止,此时这个匹配一定是最佳的(因为由可行点标的的定义,图中的任意一个完全匹配,其边权总和均不大于所有点的标号之和,而仅由可行边组成的完全匹配的边权总和等于所有点的标号之和,故这个匹配是最佳的)。一开始,求出每个点的初始标号:lx[i]=max{e.W|e.x=i}(即每个X方点的初始标号为与这个X方点相关联的权值最大的边的权值),ly[j]=0

分考场 DFS

删除回忆录丶 提交于 2020-02-06 00:32:31
问题 1874: [蓝桥杯][2017年第八届真题]分考场 时间限制: 1Sec 内存限制: 128MB 提交: 361 解决: 92 题目描述 n个人参加某项特殊考试。 为了公平,要求任何两个认识的人不能分在同一个考场。 求是少需要分几个考场才能满足条件。 输入 第一行,一个整数n(1<n<100),表示参加考试的人数。 第二行,一个整数m,表示接下来有m行数据 以下m行每行的格式为:两个整数a,b,用空格分开 (1<=a,b<=n) 表示第a个人与第b个人认识。 输出 一行一个整数,表示最少分几个考场。 样例输入 5 8 1 2 1 3 1 4 2 3 2 4 2 5 3 4 4 5 样例输出 4 提示 无 思路:从第一个人开始枚举,不断往下搜索。 代码: #include<iostream> #include<algorithm> #define rep(i,a,b) for(int i=a;i<=b;i++) #define ll long long #include<string.h> #include<queue> #include<stack> #include<cstdio> using namespace std; const int maxn=100+6; #define mod 1000000007 #define INF 0x3f3f3f3f int e

DFS深度优先遍历经典例题总结

旧城冷巷雨未停 提交于 2020-02-05 22:50:27
DFS的大概模板 void dfs ( int x ) //关于传入参数问题,根据题意而定,看在题目运行的过程中,哪些是在变得 { if ( 满足输出条件 ) { 输出解 ; return ; } if ( 目前已经没有必要进行下去的条件 ) { return ; } //剪枝操作 //如果传入的条件,还需要继续搜下去,分析每一种情况后面跟哪些情况,然后循环,每个情况(注意前提:得符合题意)都深搜一下 for ( int i = 1 ; i <= 每种情况数 ; i ++ ) if ( 满足进一步搜索条件 ) //判断是否合理 { 为进一步搜索所需要的状态打上标记 ; //是需要的状态 dfs ( t + 1 ) ; 恢复到打标记前的状态 ; //也就是说的{回溯一步} } } } 拿最经典的八皇后问题解释dfs,正常情况下,如果有一个6*6的棋盘,在第一行,选择落子,不考虑规则限制,我们有6种落子方式。 第二行,有1 2 3 4 5 6,6种落子方式。以此类推,6的6次方种情况。 但现在由于规则限制,跟bfs一样根据流程想出一个树出来。指需要按照规则取舍一下那些结点有,哪些没有即可,搜索方式上采取递归+回溯 从最终结果上,呈现出来的是从根节点一条路走到底,然后撤回底点的上一个结点,撤回后能走另一个,就走另一个 DFS传入的参数一定要能表示出每个情况的状态 例题1 P1219

DFS

↘锁芯ラ 提交于 2020-02-05 05:15:34
在LeetCode刷题时碰到一个DFS的问题 一开始是觉得用DFS解决的 =-= 对DFS不熟悉(太久没用了),用自己的方法 实在太麻烦(主要是为啥别人参数传递一个数组 可以改变数组内元素的值 我传个数组进去 咋变不鸟 以后的看看参数传递方面的东西),用DFS简单明了 题目如下 : Given a 2d grid map of '1’s (land) and '0’s (water), count the number of islands. An island is surrounded by water and is formed by connecting adjacent lands horizontally or vertically. You may assume all four edges of the grid are all surrounded by water. Example 1: Input: 11110 11010 11000 00000 Output: 1 Example 2: Input: 11000 11000 00100 00011 Output: 3 解题思路 :因为islands是被0包围起来的,所以所有垂直和水平连着的‘1’ 就是一个 islands,这个就是典型的DFS算法思想 根据一个点 深度优先遍历它的上下左右所有类似的节点即可 。

OJ常用技巧

梦想的初衷 提交于 2020-02-05 03:46:54
OJ常用技巧 0.前言 本文章主要积累一些编程中常用的 骗分技巧 。可能是针对某些特殊的样例才有用,但是也有一定的道理,可能会给大家带来一些新的启示。 1.dfs常用技巧 1.1 适当剪枝 这个不说 1.2 添加返回条件 比如说一个程序只有达到某种条件时才会返回,但是因为条件太少,返回不多,就容易出现DFS爆栈的情况,所以需要增加条件。通常情况下,可以用增加阈值的情况来限制深搜的步骤。比如说: 马的遍历 这道题,( 很明显,这是一道BFS的题 ,但是如果真的要用dfs写的话,就很容易出现超时。) 比如我用如下的代码交这道题的时候,就有一个测试点超时。【如下图所示】 这时候如果真想用dfs交题就可以尝试添加一个dfs的返回条件。代码如下: //count 代表马儿走了多少步 //(x,y) 代表当前的坐标值 void dfs ( int x , int y , int count ) { if ( x > n || x < 1 || y < 1 || y > m ) //如果越界了 return ; if ( cur > 200 ) return ; //肯定小,直接赋值 f [ x ] [ y ] = count ; if ( count + 1 < f [ x - 2 ] [ y + 1 ] ) dfs ( x - 2 , y + 1 , count + 1 ) ; //1

POJ 1426 Find The Multiple

安稳与你 提交于 2020-02-05 01:44:05
POJ 1426 Find The Multiple 题目大意: 给出一个整数n,(1 <= n <= 200)。求出任意一个它的倍数m,要求m必须只由十进制的’0’或’1’组成。 具体思路: 这道题,如果真的十进制位数不超过100位,只要超过unsigned long long的范围,加上处理大数 蒟蒻的我没有思路。但是这个题目的测试数据很小,unsigned long long可以ac。 下方的代码都是基于这个计算的。直接暴力BFS或DFS 严格按照大数的解法请可参照: 此处 dfs解法 /*dfs解法*/ # include <iostream> using namespace std ; int flag ; /*k表示递归的层数,也即m的位数*/ void dfs ( unsigned long long m , int n , int k ) { if ( flag ) { return ; } if ( m % n == 0 ) { flag = 1 ; cout << m << endl ; return ; } if ( k > 19 ) { //unsigned longlong 的范围最多为19位 return ; } dfs ( m * 10 , n , k + 1 ) ; dfs ( m * 10 + 1 , n , k + 1 ) ; } int

【DFS】勘探油田

此生再无相见时 提交于 2020-02-04 16:52:58
描述 某石油勘探公司正在按计划勘探地下油田资源。他们工作在一片长方形的地域中,首先将该地域划分为许多小正方形区域,然后使用探测设备分别探测每一块小正方形区域是否有油。若在一块小正方形区域中探测到有油,则标记为’@’,否则标记为’*’。如果两个相邻区域都为1,那么它们同属于一个石油带,一个石油带可能包含很多小正方形区域,而你的任务是要确定在一片长方形地域中有多少个石油带。所谓相邻,是指两个小正方形区域上下、左右、左上右下或左下右上同为’@’。 输入 输入数据将包含一些长方形地域数据,每个地域数据的第一行有两个正整数m和n,表示该地域为m n个小正方形所组成,如果m为0,表示所有输入到此结束。否则,后面m(1≤m≤100)行数据,每行有n(1≤n≤100)个字符,每个字符为’@’或’ ’,表示有油或无油。每个长方形地域中,’@’的个数不会超过100。 输出 每个长方形地域,输出油带的个数,每个油带值占独立的一行。油带值不会超过100。 样例输入 3 5 @ @* @ @ @* 0 0 样例输出 1 分析: DFS,3 3的矩阵内的油田都只算一个油田。 代码: #include<bits/stdc++.h> using namespace std; char c[110][110]; int fx[]={1,-1,0,0,1,-1,1,-1}; int fy[]={0,0,-1,1,1,

树的直径及应用

假如想象 提交于 2020-02-04 07:15:54
树的直径:   树的直径指树上距离最远的两点间的距离,它在树上问题上有许多应用,往往通过树的直径的性质可以将一个高时间复杂度的解法变为线性求解。 树的直径的性质: ( 1 ) (1) ( 1 ) . 对树上的任意一点而言,树上与它距离最远的点一定为树的直径的两个端点的其中之一; ( 2 ) (2) ( 2 ) .直径两端点一定是两个叶子节点; ( 3 ) (3) ( 3 ) .对于两棵树,如果第一棵树直径两端点为 ( u , v ) (u,v) ( u , v ) ,第二棵树直径两端点为 ( x , y ) (x,y) ( x , y ) ,用一条边将两棵树连接,那么新树的直径的两端点一定是 u , v , x , y u,v,x,y u , v , x , y 中的两个点; ( 4 ) (4) ( 4 ) .对于一棵树,如果在一个点的上接一个叶子节点,那么最多会改变直径的一个端点; ( 5 ) (5) ( 5 ) .若一棵树存在多条直径,那么这些直径交于一点 且交点是这些直径的中点 ; 求法: (1)搜索(dfs/bfs): 步骤:   首先,以任意一点为搜索的起点,进行第一次搜索。此次搜索得到的距起点最远的点即为直径端点之一。然后以该点为起点进行第二次搜索,所得到的距其距离最远的点即为另一个端点。 复杂度: O ( n ) O(n) O ( n ) 方便记录路径 (2)树形dp