深度优先搜索(Depth First Search)是搜索的手段之一。它是从某个状态开始,不断的转移状态直到无法转移,然后退回到前一步的状态,继续转移到其他的状态,如此不断的重复,直至找到最终的解。

其大致的过程如下:
 (1)访问搜索到的未被访问的邻接点;
 (2)将此顶点标记为已访问节点;
 (3)搜索该顶点的未被访问的邻接点,若该邻接点存在,则从此邻接点开始进行同样的访问和搜索。

说到深搜,我就想起了我多年前玩的一个纯文字 wap 页游,游戏里有一个地下迷宫,目标是找出口打怪开宝箱。当时我玩这个游戏的思路就和深搜的解题思路一模一样。游戏还原链接(https://www.windfamily.cn/module/games/maze.html)。深搜的解题思路就好像走那个迷宫,一开始找到一个可以走的方向,不停的往这个方向走,路上看到了其它路口,记住,如果一个方向走不通,还可以回来走这个方向。当那个方向被围住或者走不通时,就往回走,直到碰到最近的之前遇到过的路口,然后一样的往这个方向走,重复上面的步骤。深搜具体实现时和它的区别就是当一个方向走到头时你不用往回走,因为你走过的地方都被标记过,不能走了,系统(递归回溯)会帮你自动跳回到你之前遇到过的最近的路口。

先看一道例题:

1. 白与黑:http://acm.nefu.edu.cn/problemShow.php?problem_id=784

#include <bits/stdc++.h>using namespace std;int w,h;
int num;
string a[101];
int dir[4][2]={{1,0},{-1,0},{0,1},{0,-1}};        //搜索的方向int dfs(int x,int y)
{a[x][y]='#';            //走过的路都给它标记上for(int i=0;i<4;i++)    //这个for循环就是在某点上看看四个方向能不能走{int newx=x+dir[i][0];int newy=y+dir[i][1];if(newx>=0 && newx<h && newy>=0 && newy<w && a[newx][newy]!='#'){num++;dfs(newx,newy);            //其实递归有储存发现的路口的意味}}
}int main()
{int i,j;while(scanf("%d%d",&w,&h)!=-1){if(w==0 && h==0) break;num=1;for(i=0;i<h;i++) cin>>a[i];   //必须用cin,string用cin才能被正确处理for(i=0;i<h;i++){for(j=0;j<w;j++)if(a[i][j]=='@'){dfs(i,j);break;}}printf("%d\n",num);}
}

说明一下,生成newx,newy后,如果符合if条件进入if就说明这一步可以走,而当dfs(newx,newy)的时候就说明这一步现在已经走了(因为它马上要被标记为'#'),现在要考虑这步走完的下一步。

2. 搜索入门:http://acm.nefu.edu.cn/problemShow.php?problem_id=912

#include <bits/stdc++.h>using namespace std;
string a[5];
int flag;
int dir[4][2]={{1,0},{-1,0},{0,1},{0,-1}};
int dfs(int x,int y)
{a[x][y]='*';for(int i=0;i<4;i++){int newx=x+dir[i][0];int newy=y+dir[i][1];if(newx>=0 && newx<4 && newy>=0 && newy<4 && a[newx][newy]=='#'){if(newx==3 && newy==3){flag=1;break;}else dfs(newx,newy);}}
}
int main()
{int t;scanf("%d",&t);while(t--){flag=0;for(int i=0;i<4;i++) cin>>a[i];dfs(0,0);if(flag==0) printf("NO\n");else printf("YES\n");}
}

上一题懂了这题自然没问题。

3. 迷宫寻路:http://acm.nefu.edu.cn/problemShow.php?problem_id=558

从这题中得到一个惨痛的教训:i一定不能是全局的(因为其它地方也用到i所以小心啊),否则递归迭代的时候i会累加。

同时提供除了利用flag判断能否到达终点的另一种方法。

#include <bits/stdc++.h>using namespace std;int n,m;
int stx,sty,enx,eny;
string a[1005];
int dir[4][2]={{1,0},{-1,0},{0,1},{0,-1}};void dfs(int x,int y)
{a[x][y]='#';for(int i=0;i<4;i++)        //这里的i一定不能设成全局的{int newx=x+dir[i][0];int newy=y+dir[i][1];if(newx>=0 && newx<n && newy>=0 && newy<m && a[newx][newy]=='*'){dfs(newx,newy);}}
}
int main()
{while(scanf("%d%d",&n,&m)!=-1){stx=sty=enx=eny=-1;for(int i=0;i<n;i++) cin>>a[i];for(int i=0;i<n;i++)for(int j=0;j<m;j++){if((i==0 || i==n-1 || j==0 || j==m-1) && a[i][j]=='*'){if(stx==-1) stx=i,sty=j;else enx=i,eny=j;}}dfs(stx,sty);if(a[enx][eny]!='#') printf("NO\n");else printf("YES\n");}
}

4. 最大黑色区域:http://acm.nefu.edu.cn/problemShow.php?problem_id=1694

这道题一开始看上去没啥思路,其实很简单,就是一个大矩阵可以分成很多各小矩阵来搜(因为各区域面积被0隔离),只要遍历矩阵,看到1就开始搜,得到该部分面积(1个数)的最大值,然后进行比较即可。

然后这道题一开始踩了一个坑,就是maxs只能初始化为0,因为样例中可能存在全为0的情况。

#include <bits/stdc++.h>using namespace std;int n,m;
int maxs,nows;
int a[1005][1005];
int dir[4][2]={{1,0},{-1,0},{0,1},{0,-1}};
int dfs(int x,int y)
{nows++;a[x][y]=0;for(int i=0;i<4;i++){int newx=x+dir[i][0];int newy=y+dir[i][1];if(newx>=0 && newx<n && newy>=0 && newy<m && a[newx][newy]==1){dfs(newx,newy);}}}
int main()
{scanf("%d%d",&n,&m);maxs=0;        //这里for(int i=0;i<n;i++)for(int j=0;j<m;j++)scanf("%d",&a[i][j]);for(int i=0;i<n;i++)for(int j=0;j<m;j++)if(a[i][j]==1){nows=0;dfs(i,j);maxs=max(maxs,nows);}printf("%d\n",maxs);
}

5. 猴群:http://acm.nefu.edu.cn/problemShow.php?problem_id=1696

这道题与第四题极为相似,除了一些细节方面,思路和第四题一样。

#include <bits/stdc++.h>using namespace std;
int n,m;
int num;
string a[105];
int dir[4][2]={{1,0},{-1,0},{0,1},{0,-1}};
int dfs(int x,int y)
{a[x][y]='0';for(int i=0;i<n;i++){int newx=x+dir[i][0];int newy=y+dir[i][1];if(newx>=0 && newx<n && newy>=0 && newy<m && a[newx][newy]!='0'){dfs(newx,newy);}}
}
int main()
{scanf("%d%d",&n,&m);num=0;for(int i=0;i<n;i++) cin>>a[i];for(int i=0;i<n;i++){for(int j=0;j<m;j++){if(a[i][j]!='0'){num++;dfs(i,j);}}}printf("%d\n",num);
}

6. 面积:http://acm.nefu.edu.cn/problemShow.php?problem_id=1699

这道题思路就是从为0的边缘开始搜,把搜到的0变为1,最后统计剩余0的个数即可。

#include <bits/stdc++.h>using namespace std;
int num;
int a[15][15];
const int n=10;
int dir[4][2]={{-1,0},{1,0},{0,1},{0,-1}};
int dfs(int x,int y)
{a[x][y]=1;for(int i=0;i<4;i++){int newx=x+dir[i][0];int newy=y+dir[i][1];if(newx>=0 && newx<n && newy>=0 && newy<n && a[newx][newy]==0){dfs(newx,newy);}}
}int main()
{for(int i=0;i<n;i++)for(int j=0;j<n;j++)scanf("%d",&a[i][j]);for(int i=0;i<n;i++)for(int j=0;j<n;j++)if((i==0 || i==n-1 || j==0 || j==n-1) && a[i][j]==0)dfs(i,j);num=0;for(int i=0;i<n;i++)for(int j=0;j<n;j++)if(a[i][j]==0) num++;printf("%d\n",num);
}

7.  数的划分:http://acm.nefu.edu.cn/problemShow.php?problem_id=1776

将整数 n 分成 k 份,且每份不能为空,问有多少种不同的分法。
当 n=7, k=3 时,下面三种分法被认为是相同的:1,1,5; 1,5,1; 5,1,1Input
一行两个数 n, kOutput
一行一个整数,即不同的分法数。

为什么说这道题也能搜索呢?请看下图:

例子中数据n=7,k=3,答案是4。

对于一个数,我们可以第一次可以将它从划分为1~n的数,图中给出了第一次划分为1的情况,对于划分为1的情况,因为题目中说数字相同而顺序不同的组合看成一种,那么我们可以假设后划分的数大于等于先划分的数,于是第二次就可以从1~n-1再次划分,第三次可以从1~n-2划分。

如果对于每一层都进行这样的划分,那么就可以形成一棵庞大的树,我们要做的就是用深搜从不停遍历一个分支到底,看这个分支上数的和等不等于n,然后回退到上一层。是不是还是和之前的走迷宫思路一样?

代码:递归实现

#include <bits/stdc++.h>using namespace std;int n,k;
int num=0;int dfs(int nown,int sum,int nowk)  //nown表示当分支的节点上的数,sum表示分支上的和,nowk表示进行到第几层
{if(nowk==k)        //如果遍历完k层,就判断它的和是否为n,是就说明找到一种情况。{if(sum==n) num++;return 0;}for(int i=nown;sum+i*(k-nowk)<=n;i++)        //生成树(利用递归一次只生成一个分支){dfs(i,sum+i,nowk+1);}
}int main()
{scanf("%d%d",&n,&k);dfs(1,0,0);            //从1开始划分printf("%d\n",num);
}

8. 01迷宫:http://acm.nefu.edu.cn/problemShow.php?problem_id=1702

这道题的解题思路:就是看看有多少个连通的区域,然后看看每一点属于哪个连通区域。要明确在起点在0时能走到的连通区域内,若以1为起点,也能走遍这个区域。判断相邻两点之间能不能走,可以用异或判断,只有异或值为1才可以走。

#include <bits/stdc++.h>using namespace std;int n,m;
int connectnum;       //连通区域个数
string a[1005];
int connectarea[1000005];    //某连通区域能移动的格子数
int wcb[1005][1005];  //which connectarea belong某点属于哪一个连通区域
int dir[4][2]={{-1,0},{1,0},{0,1},{0,-1}};int dfs(int x,int y)
{wcb[x][y]=connectnum;   //确定格子属于哪个连通区域connectarea[connectnum]++;  //当前连通区域格子数加1int t=a[x][y]-'0';for(int i=0;i<4;i++){int newx=x+dir[i][0];int newy=y+dir[i][1];if(newx>=0 && newx<n && newy>=0 && newy<n && wcb[newx][newy]==0 && ((a[newx][newy]-'0')^t)==1){dfs(newx,newy);}}
}int main()
{scanf("%d%d",&n,&m);for(int i=0;i<n;i++) cin>>a[i];for(int i=0;i<n;i++){for(int j=0;j<n;j++){if(wcb[i][j]==0){connectnum++;dfs(i,j);}}}for(int i=0;i<m;i++){int in,jn;scanf("%d%d",&in,&jn);int belong=wcb[in-1][jn-1];printf("%d\n",connectarea[belong]);}
}

9. 奇怪的电梯:http://acm.nefu.edu.cn/problemShow.php?problem_id=1697

与之前不同的是,这题方向是一维的,只能上下移动,确定起点后,搜就是了,看能不能到终点,能就和最短距离比取小。

需要注意的是,这题同样需要标记走过的地方,否则会死循环,走到哪里就把那里标记为不能走的,不要担心你担心可能出现的情况,因为这轮的标记只对这轮有效,递归回退的时候会把标记恢复为没走过,从而进行让下一分支继续走。

这题绊了我好久,思路是对的,递归的方法用错了,当前位置和按电梯的次数是要放在进行递归的,否则次数没办法回退。还有就是要注意剪枝,否则直接TLE。

先看正确代码:

#include <bits/stdc++.h>using namespace std;int n,a,b;
int minn=9999999;
int lift[205],vis[205];
int dir[2]={1,-1};int dfs(int now,int pressnum)
{if(now==b){minn=min(minn,pressnum);return 0;}if(pressnum<minn)        //剪枝for(int i=0;i<2;i++){int newnow=now+dir[i]*lift[now];if(newnow>=1 && newnow<=n && vis[newnow]==0){vis[newnow]=1;dfs(newnow,pressnum+1);    //这里的千万不能用++,否则会影响同级分支,失去回退效果vis[newnow]=0;             //之前说的标记回退}}
}int main()
{scanf("%d%d%d",&n,&a,&b);for(int i=1;i<=n;i++) scanf("%d",&lift[i]);memset(vis,0,sizeof(vis));vis[a]=1;if(a==b)                //这个if其实可以不要{printf("0\n");return 0;}dfs(a,0);if(minn==9999999) printf("%d\n",-1);else printf("%d\n",minn);
}

然后看我之前写的错误代码:

#include <bits/stdc++.h>
using namespace std;
int n,a,b;
int num,minnum=99999999;
int lift[2005];
int vis[2005];int dir[3]={1,-1};int dfs(int from)
{if(num<minnum)            //这个地方必须进行剪枝,否则超时,但这么做else情况num无法回退for(int i=0;i<2;i++){int to=from+dir[i]*lift[from];if(to>=1 && to<=n && vis[to]==0){num++;vis[to]=1;if(to==b){minnum=min(minnum,num);return 0;}dfs(to);num--;vis[to]=0;}}
}int main()
{scanf("%d%d%d",&n,&a,&b);for(int i=1;i<=n;i++) scanf("%d",&lift[i]);num=0;if(a==b)            //这种情况下必须写{printf("0\n");return 0;}vis[a]=1;dfs(a);if(minnum>=99999999) printf("-1\n");else printf("%d\n",minnum);
}

10. 艾拉的选举:http://acm.nefu.edu.cn/problemShow.php?problem_id=1672

这题应该算是压轴题了,有些复杂。

首先从第一个评委对第一个选手评分开始搜索,然后继续进行第一个评委对后续评委的评分,当第一个评委评完分后换下一个评委继续评分搜索,当所有评委都评完分后,进行排序,num[order][名次]++;整棵树应该是这样的(只画出部分):

看代码:

#include <bits/stdc++.h>using namespace std;
struct student{    //用结构体储存那啥的序号,以及当前拥有的分数(开始是初始分数)int order;int mark;
}a[5];int n,m;
int b[5];          //储存评委能打的分数
int vis[5][5];     //用于第x个评委是否用过第i个分数
int num[5][5];     //储存第i个那啥获得第j名的次数bool cmp(student a,student b)        //当所有评委对所有那啥评完分进行排序时的比较函数
{if(a.mark!=b.mark) return a.mark>b.mark;else return a.order<b.order;
}int dfs(int x,int y)
{if(y==n+1)        //当一个评委对所有选手评完分后,换下一个评委{dfs(x+1,1);return 0;}if(x==m+1)        //当所有评委对所有选手评完分后对分数进行排序{student t[5];    //用临时数组进行排序,否则递归回退的时候会减错位置for(int i=1;i<=n;i++) t[i]=a[i];sort(t+1,t+n+1,cmp);for(int j=1;j<=n;j++)  num[t[j].order][j]++;return 0;}for(int i=1;i<=n;i++)    //评委对第1位到n位选手评分{if(vis[x][i]==0)    //确定该评委没用过某一分数{vis[x][i]=1;a[y].mark=a[y].mark+b[i];dfs(x,y+1);vis[x][i]=0;      //递归回退a[y].mark-=b[i];   //要用临时数组排序的原因}}
}
int main()
{scanf("%d%d",&n,&m);for(int i=1;i<=n;i++){a[i].order=i;scanf("%d",&a[i].mark);}for(int i=1;i<=n;i++) scanf("%d",&b[i]);dfs(1,1);            //搜索起点:第1个评委对1个选手评分for(int i=1;i<=n;i++){for(int j=1;j<=n;j++)if(j==n) printf("%d\n",num[i][j]);else printf("%d ",num[i][j]);}
}

这道题还可以暴力循化:

#include<bits/stdc++.h>
using namespace std;
long long b1[30][6];
long long a[6];
long long b[6];
long long x,y,z,q;
long long js[6][6];
struct sz{
long long zhi;
int wz;
}cz[6];
bool com(sz a,sz b){
if(a.zhi!=b.zhi)
return a.zhi>b.zhi;
else return a.wz<b.wz;
}
int main()
{int i,j,m,n,i2,i3,i4,i1;cin>>n>>m;memset(js,0,sizeof(js));if(n==1){cin>>x>>y;printf("1\n");}else if(n==2){x=0,y=0;for(i=1;i<=2;i++)scanf("%lld",&a[i]);for(i=1;i<=2;i++)scanf("%lld",&b[i]);b1[1][1]=b[1];b1[1][2]=b[2];b1[2][1]=b[2];b1[2][2]=b[1];if(m==1){for(i=1;i<=2;i++){x=a[1]+b1[i][1];y=a[2]+b1[i][2];if(x>=y){js[1][1]++;js[2][2]++;}else {js[1][2]++;js[2][1]++;}}}if(m==2){for(i=1;i<=2;i++)for(i1=1;i1<=2;i1++){x=a[1]+b1[i][1]+b1[i1][1];y=a[2]+b1[i][2]+b1[i1][2];if(x>=y){js[1][1]++;js[2][2]++;}else {js[1][2]++;js[2][1]++;}}}if(m==3){for(i=1;i<=2;i++)for(i1=1;i1<=2;i1++)for(i2=1;i2<=2;i2++){x=a[1]+b1[i][1]+b1[i1][1]+b1[i2][1];y=a[2]+b1[i][2]+b1[i1][2]+b1[i2][2];if(x>=y){js[1][1]++;js[2][2]++;}else {js[1][2]++;js[2][1]++;}}}if(m==4){for(i=1;i<=2;i++)for(i1=1;i1<=2;i1++)for(i2=1;i2<=2;i2++)for(i3=1;i3<=2;i3++){x=a[1]+b1[i][1]+b1[i1][1]+b1[i2][1]+b1[i3][1];y=a[2]+b1[i][2]+b1[i1][2]+b1[i2][2]+b1[i3][2];if(x>=y){js[1][1]++;js[2][2]++;}else {js[1][2]++;js[2][1]++;}}}for(i=1;i<=n;i++){for(j=1;j<n;j++)printf("%lld ",js[i][j]);printf("%lld\n",js[i][n]);}}else if(n==3){x=0,y=0;for(i=1;i<=3;i++)scanf("%lld",&a[i]);for(i=1;i<=3;i++)scanf("%lld",&b[i]);b1[1][1]=b[1];b1[1][2]=b[2];b1[1][3]=b[3];b1[2][1]=b[1];b1[2][2]=b[3];b1[2][3]=b[2];b1[3][1]=b[2];b1[3][2]=b[1];b1[3][3]=b[3];b1[4][1]=b[2];b1[4][2]=b[3];b1[4][3]=b[1];b1[5][1]=b[3];b1[5][2]=b[2];b1[5][3]=b[1];b1[6][1]=b[3];b1[6][2]=b[1];b1[6][3]=b[2];if(m==1){for(i=1;i<=6;i++){x=a[1]+b1[i][1];y=a[2]+b1[i][2];z=a[3]+b1[i][3];cz[0].wz=1;cz[0].zhi=x;cz[1].wz=2;cz[1].zhi=y;cz[2].wz=3;cz[2].zhi=z;sort(cz,cz+3,com);for(j=1;j<=3;j++)js[cz[j-1].wz][j]++;}}if(m==2){for(i=1;i<=6;i++)for(i1=1;i1<=6;i1++){x=a[1]+b1[i][1]+b1[i1][1];y=a[2]+b1[i][2]+b1[i1][2];z=a[3]+b1[i][3]+b1[i1][3];cz[0].wz=1;cz[0].zhi=x;cz[1].wz=2;cz[1].zhi=y;cz[2].wz=3;cz[2].zhi=z;sort(cz,cz+3,com);for(j=1;j<=3;j++)js[cz[j-1].wz][j]++;}}if(m==3){for(i=1;i<=6;i++)for(i1=1;i1<=6;i1++)for(i2=1;i2<=6;i2++){x=a[1]+b1[i][1]+b1[i1][1]+b1[i2][1];y=a[2]+b1[i][2]+b1[i1][2]+b1[i2][2];z=a[3]+b1[i][3]+b1[i1][3]+b1[i2][3];cz[0].wz=1;cz[0].zhi=x;cz[1].wz=2;cz[1].zhi=y;cz[2].wz=3;cz[2].zhi=z;sort(cz,cz+3,com);for(j=1;j<=3;j++)js[cz[j-1].wz][j]++;}}if(m==4){for(i=1;i<=6;i++)for(i1=1;i1<=6;i1++)for(i2=1;i2<=6;i2++)for(i3=1;i3<=6;i3++){x=a[1]+b1[i][1]+b1[i1][1]+b1[i2][1]+b1[i3][1];y=a[2]+b1[i][2]+b1[i1][2]+b1[i2][2]+b1[i3][2];z=a[3]+b1[i][3]+b1[i1][3]+b1[i2][3]+b1[i3][3];cz[0].wz=1;cz[0].zhi=x;cz[1].wz=2;cz[1].zhi=y;cz[2].wz=3;cz[2].zhi=z;sort(cz,cz+3,com);for(j=1;j<=3;j++){js[cz[j-1].wz][j]++;}}}for(i=1;i<=n;i++){for(j=1;j<n;j++)printf("%lld ",js[i][j]);printf("%lld\n",js[i][n]);}}else if(n==4){x=1,y=0,z=0,q=0;for(i=1;i<=4;i++)scanf("%lld",&a[i]);for(i=1;i<=4;i++)scanf("%lld",&b[i]);for(i=1;i<=4;i++)for(i1=1;i1<=4;i1++)if(i1==i)continue;elsefor(i2=1;i2<=4;i2++)if(i2==i1||i2==i)continue;elsefor(i3=1;i3<=4;i3++)if(i3==i||i3==i1||i3==i2)continue;else{b1[x][1]=b[i];b1[x][2]=b[i1];b1[x][3]=b[i2];b1[x][4]=b[i3];x++;}if(m==1){for(i=1;i<=24;i++){x=a[1]+b1[i][1];y=a[2]+b1[i][2];z=a[3]+b1[i][3];q=a[4]+b1[i][4];cz[0].wz=1;cz[0].zhi=x;cz[1].wz=2;cz[1].zhi=y;cz[2].wz=3;cz[2].zhi=z;cz[3].wz=4;cz[3].zhi=q;sort(cz,cz+4,com);for(j=1;j<=4;j++)js[cz[j-1].wz][j]++;}}if(m==2){for(i=1;i<=24;i++)for(i1=1;i1<=24;i1++){x=a[1]+b1[i][1]+b1[i1][1];y=a[2]+b1[i][2]+b1[i1][2];z=a[3]+b1[i][3]+b1[i1][3];q=a[4]+b1[i][4]+b1[i1][4];cz[0].wz=1;cz[0].zhi=x;cz[1].wz=2;cz[1].zhi=y;cz[2].wz=3;cz[2].zhi=z;cz[3].wz=4;cz[3].zhi=q;sort(cz,cz+4,com);for(j=1;j<=4;j++)js[cz[j-1].wz][j]++;}}if(m==3){for(i=1;i<=24;i++)for(i1=1;i1<=24;i1++)for(i2=1;i2<=24;i2++){x=a[1]+b1[i][1]+b1[i1][1]+b1[i2][1];y=a[2]+b1[i][2]+b1[i1][2]+b1[i2][2];z=a[3]+b1[i][3]+b1[i1][3]+b1[i2][3];q=a[4]+b1[i][4]+b1[i1][4]+b1[i2][4];cz[0].wz=1;cz[0].zhi=x;cz[1].wz=2;cz[1].zhi=y;cz[2].wz=3;cz[2].zhi=z;cz[3].wz=4;cz[3].zhi=q;sort(cz,cz+4,com);for(j=1;j<=4;j++)js[cz[j-1].wz][j]++;}}if(m==4){for(i=1;i<=24;i++)for(i1=1;i1<=24;i1++)for(i2=1;i2<=24;i2++)for(i3=1;i3<=24;i3++){x=a[1]+b1[i][1]+b1[i1][1]+b1[i2][1]+b1[i3][1];y=a[2]+b1[i][2]+b1[i1][2]+b1[i2][2]+b1[i3][2];z=a[3]+b1[i][3]+b1[i1][3]+b1[i2][3]+b1[i3][3];q=a[4]+b1[i][4]+b1[i1][4]+b1[i2][4]+b1[i3][4];cz[0].wz=1;cz[0].zhi=x;cz[1].wz=2;cz[1].zhi=y;cz[2].wz=3;cz[2].zhi=z;cz[3].wz=4;cz[3].zhi=q;sort(cz,cz+4,com);for(j=1;j<=4;j++)js[cz[j-1].wz][j]++;}}for(i=1;i<=n;i++){for(j=1;j<n;j++)printf("%lld ",js[i][j]);printf("%lld\n",js[i][n]);}}return 0;
}

写完这个需要相当的毅力,一度令之前思路一复杂的时候就想放弃治疗的我自惭形秽。路漫漫其修远兮,加油 QWQ。

DFS-深度优先搜索(深搜)相关推荐

  1. 【算法】蓝桥杯dfs深度优先搜索之排列组合总结

    [导航] 上一篇文章 → <[算法]蓝桥杯dfs深度优先搜索之凑算式总结>   为了重申感谢之意,再次声明下文的大部分灵感均来自于[CSDN]梅森上校<JAVA版本:DFS算法题解两 ...

  2. dfs深度优先搜索_图的深度优先搜索(DFS)

    dfs深度优先搜索 Depth First Search (DFS) is an algorithm that searches a graph/tree, in a depth-wise manne ...

  3. 【蓝桥杯C/C++】专题五:DFS深度优先搜索

    专题五:DFS深度优先搜索 目录 专题五:DFS深度优先搜索 前言 什么是回溯法 如何理解回溯法 回溯法解决的问题 回溯法模板 1 .回溯函数模板返回值以及参数 2. 回溯函数终止条件 3 .回溯搜索 ...

  4. “暴力美学1”——DFS深度优先搜索

    作为新时代青年,"暴力"二字似乎离我们十分遥远,大多数时候我们只能够在电影或者电视剧上接触这个概念 暴力二字或许是个贬义词,但若是我们在后面加上美学二字,或许就是一个值得推敲的词汇 ...

  5. 【算法】蓝桥杯dfs深度优先搜索之图连通总结

    前言 上两篇文章 → <[算法]蓝桥杯dfs深度优先搜索之排列组合总结>      → <[算法]蓝桥杯dfs深度优先搜索之凑算式总结>   为了重申感谢之意,第三次声明下文的 ...

  6. 图:DFS(深度优先搜索)图解分析代码实现

    文章目录 一.简介 二.图的建立 2.1建立图类 2.2建立图 三.DFS 3.1图解 3.2代码 一.简介 图的DFS(深度优先搜索)与BFS(广度优先搜索)是图的两种遍历方式. 主要区别在于当到达 ...

  7. DFS——深度优先搜索基础

    [0]README 0.1) 本文总结于 数据结构与算法分析, 源代码均为原创, 旨在 review DFS--深度优先搜索 的基础知识: [1]深度优先搜索的应用 1.1)深度优先搜索算法描述(转自 ...

  8. DFS(深度优先搜索)算法实现

    2 DFS算法 DFS(深度优先搜索)算法,搜索过程是类似于不撞南墙不回头的意思,DFS一般使用堆栈(先入后出)这种数据结构实现,由此一来,以初始起点为中心进行搜索,首先是周围点加入到堆栈中,起始点搜 ...

  9. 张三踩瓷砖:C++用DFS深度优先搜索解POJ1979 Red and Black问题

    POJ1979 Red and Black 题目链接: POJ1979 Red and Black 简单理解一下题目: 张三站在一个长方形的房间里,房间里铺满了方形瓷砖,瓷砖有红色和黑色两种,他站在其 ...

最新文章

  1. [你必须知道的.NET] 开篇有益
  2. 20162317 2016-2017-2 《程序设计与数据结构》第8周学习总结
  3. 简述流水线基本工作原理 计算机,自动化专业计算机技术基础作业题(50题)
  4. C语言 Condition variables
  5. git学习(二):git config命令
  6. atitit.javascript js 上传文件的本地预览
  7. C语言编写学生管理系统
  8. GetTickCount函数在linux下的实现
  9. 计算机office报名时间,计算机二级office每年的报名时间和考试时间是什么时候?...
  10. 历史_美股和美债的联动关系
  11. c语言编写作息时间表_嵌入式杂谈之中断向量表
  12. 关于“程序员996”,互联网大神发话了,能顶用吗?
  13. 基础知识点|命令执行漏洞相关总结
  14. 华为手机便签有扫描的功能么
  15. 360度全景图片怎么拍摄?
  16. 1086:角谷猜想(C C++)
  17. 硬件设计原理图Checklist 参考案例二 【转载】
  18. Zhong__安装配置ElasticSearch
  19. SAP-HR模块-常用T-CODE
  20. Discuz!教程之从码云下载的Discuz!代码安装后个人资料页面乱码问题修复

热门文章

  1. python股票自动交易从零开始-自动交易python
  2. spark 大型项目实战(三十一): --性能调优之在实际项目中使用fastutil优化数据格式
  3. pytorch:tensor与numpy转换 .cpu.numpy()和.numpy() torch.from_numpy VS torch.Tensor
  4. 做技术要有一颗平常心
  5. 几张图解释清楚死锁+wait和notify的搭配使用
  6. ABP入门系列(7)——分页实现_0
  7. 在外远程桌面控制家里的电脑
  8. Android 各国语言缩写-各国语言简称 .
  9. Java 最常见的 200+ 面试题汇总 ,大厂不再是梦
  10. 网页设计与制作(项目二--响应式页面制作)