一、树的遍历
二、图的遍历
例题:危险系数
/*
这道题可以用dfs来解决。如果从a到b可走的n条路中,其中某个点出现了n次,则这个点就是割点,去掉它则不通。
从a到b有n种方法,则n种方法都路过的点就是关键点
*/
#include<stdio.h>
#include<string.h>
int graph[1005][1005];
int visited[1005];
int n;
int times[1005];
int ans=0;
void dfs(int x,int y){
int i;
visited[x]=1;
if(x==y){
ans++;
for(i=1;i<=n;i++){
if(visited[i]==1)
times[i]++;
}
}
else{
for(i=1;i<=n;i++){
if((graph[x][i]!=0)&&(visited[i]==0)){
dfs(i,y);
visited[i]=0;
}
}
}
}
int main(){
int m;
int i;
int x,y;
int count=0;
scanf("%d %d",&n,&m);
memset(graph,0,sizeof(graph));
memset(visited,0,sizeof(visited));
memset(times,0,sizeof(times));
for(i=1;i<=m;i++){
scanf("%d %d",&x,&y);
graph[x][y]=1;
graph[y][x]=1;
}
scanf("%d %d",&x,&y);
dfs(x,y);
for(i=1;i<=n;i++){
if(ans==times[i])
count++;
}
//因为x和y也算进来,故要减掉
if(ans==0){
printf("-1");
}else{
printf("%d",count-2);
}
return 0;
}
三、固定节点遍历矩阵
例题:剪格子
/*
回溯法
dfs上下左右都要走,如果走过就记录下来
走步数,走的值
回溯前加,则回溯后减
该回溯需要回溯的值,1、是否走过,2、所走步数,3、所走值
注意该题是先输入列,再输入行
方法:
就是确定结束条件
dsf遍历上下左右,却判断是否已经走了和越界
走一个方向时,要确定走直接要加什么,然后走结束后要减掉之前加的
*/
#include<stdio.h>
#include<string.h>
int matrix[15][15];
int record[15][15];
int sum=0;
int n,m;
int count=0x3f3f3f3f;
int strcount=0;
int strsum=0;
//减少代码
int nextt[4][4]={{0,1},{1,0},{0,-1},{-1,0}};
void recall(int x,int y){
//判断是否相等,是则退出
if(strsum==sum-strsum){
if(strcount<count)
count=strcount;
return ;
}
else{
int i;
for(i=0;i<4;i++){
int xx=nextt[i][0]+x;
int yy=nextt[i][1]+y;
//越界判断
if(xx<0||xx>=n||yy<0||yy>=m)
continue;
//是否遍历过判断
if(!record[xx][yy]){
record[xx][yy]=1;
strcount++;
strsum+=matrix[xx][yy];
recall(xx,yy);
strsum-=matrix[xx][yy];
strcount--;
record[xx][yy]=0;
}
}
// //走上
// if(x-1>=0&&x-1<n&&record[x-1][y]==0){
// record[x-1][y]=1;
// strcount++;
// strsum+=matrix[x-1][y];
// recall(x-1,y);
// record[x-1][y]=0;
// strcount--;
// strsum-=matrix[x-1][y];
// }
// //走下
// if(x+1>=0&&x+1<n&&record[x+1][y]==0){
// record[x+1][y]=1;
// strcount++;
// strsum+=matrix[x+1][y];
// recall(x+1,y);
// record[x+1][y]=0;
// strcount--;
// strsum-=matrix[x+1][y];
// }
// //走左
// if(y-1>=0&&y-1<m&&record[x][y-1]==0){
// record[x][y-1]=1;
// strcount++;
// strsum+=matrix[x][y-1];
// recall(x,y-1);
// record[x][y-1]=0;
// strcount--;
// strsum-=matrix[x][y-1];
// }
// //走右
// if(y+1>=0&&y+1<m&&record[x][y+1]==0){
// record[x][y+1]=1;
// strcount++;
// strsum+=matrix[x][y+1];
// recall(x,y+1);
// record[x][y+1]=0;
// strcount--;
// strsum-=matrix[x][y+1];
// }
}
}
int main(){
int i,j;
scanf("%d%d",&m,&n);
for(i=0;i<n;i++){
for(j=0;j<m;j++){
scanf("%d",&matrix[i][j]);
sum+=matrix[i][j];
}
}
if(sum%2!=0){
printf("0");
}else{
memset(record,0,sizeof(record));
strcount++;
strsum+=matrix[0][0];
record[0][0]=1;
recall(0,0);
if(count==0x3f3f3f3f){
printf("0");
}else{
printf("%d",count);
}
}
return 0;
}
四、不固定节点遍历矩阵
例题:剪邮票
#include<stdio.h>
//116
int sum;
int isOK(int a[],int n,int m){ //判断全排列是否重复
if(m>n){
for(;n<m;n++){
if(a[n]==a[m])
return false;
}
}
return true;
}
void swap(int *i,int *j){ //两数交换
int n=*i;
*i=*j;
*j=n;
return;
}
void dsf(int b[3][4],int p,int q){ //dsf找连同数
b[p][q]=0;
if(p>0&&b[p-1][q]==1) dsf(b,p-1,q);
if(p<2&&b[p+1][q]==1) dsf(b,p+1,q);
if(q>0&&b[p][q-1]==1) dsf(b,p,q-1);
if(q<3&&b[p][q+1]==1) dsf(b,p,q+1);
return;
}
int check(int a[]){ //判断5个数字是否相连
int b[3][4];
int cnt=0;
for(int i=0;i<3;i++){
for(int j=0;j<4;j++){
b[i][j]=a[i*4+j];
}
}
for(int i=0;i<3;i++){
for(int j=0;j<4;j++){
if(b[i][j]==1){
dsf(b,i,j);
cnt++;
}
}
}
return cnt==1;
}
void perm(int a[],int p,int q){ // 全排列
if(p==q){
if(check(a))
sum++;
}
else{
for(int i=p;i<=q;i++){
if(isOK(a,p,i))
{
swap(&a[i],&a[p]);
perm(a,p+1,q);
swap(&a[i],&a[p]);
}
}
}
}
int main(){
sum=0;
int a[12]={0,0,0,0,0,0,0,1,1,1,1,1};
perm(a,0,11);
printf("%d",sum);
return 0;
}
五、方格以点作区分,而不是以单元格
例题:方格分割
#include<stdio.h>
#define N 6
int next[4][2]={{0,-1},{0,1},{-1,0},{1,0}};
int matrix[7][7];
int count=0;
void dfs(int x,int y){
int i;
int xx;
int yy;
if(x<=0||y<=0||x>=N||y>=N){
count++;
}else{
for(i=0;i<4;i++){
xx=next[i][0]+x;
yy=next[i][1]+y;
if(matrix[xx][yy]!=1){
matrix[xx][yy]=1;
matrix[6-xx][6-yy]=1;
dfs(xx,yy);
matrix[xx][yy]=0;
matrix[6-xx][6-yy]=0;
}
}
}
}
int main(){
matrix[N/2][N/2]=1;
dfs(N/2,N/2);
printf("%d",count/4);
return 0;
}