枯木逢春不在茂,年少且惜镜边人
这周继续完成上周么有完成的目标,然后学学java,学学图的遍历,学学浴谷上的题,然后上天.
1.水管工问题
#include<stdio.h>
int book[51][51];
int a[51][51],n,m,flag=0;
struct note
{
int x;
int y;
} s[100];
int top=0;
void dfs(int x,int y,int front)
{
int i;
if(x==n&&y==m+1)
{
flag=1;
for(i=1;i<=top;i++)
printf("(%d,%d)",s[i].x,s[i].y);
}
if(x<1||x>n||y<1||y>m)
return ;
if(book[x][y]==1)
return ;
book[x][y]=1;
top++;
s[top].x=x;
s[top].y=y;
if(a[x][y]>=5&&a[x][y]<=6)
{
if(front==1)
dfs(x,y+1,1);
if(front==2)
dfs(x+1,y,2);
if(front==3)
dfs(x,y-1,3);
if(front==4)
dfs(x-1,y,4);
}
if(a[x][y]>=1&&a[x][y]<5)
{
if(front==1)//左
{
dfs(x+1,y,2);
dfs(x-1,y,4);
}
if(front==2)//上
{
dfs(x,y-1,3);
dfs(x,y+1,1);
}
if(front==3)//右
{
dfs(x-1,y,4);
dfs(x+1,y,2);
}
if(front==4)//下
{
dfs(x,y-1,3);
dfs(x,y+1,1);
}
}
book[x][y]=0;
top--;
return ;
}
int main()
{
int i,j;
scanf("%d %d",&n,&m);
for(i=1;i<=n;i++)
for(j=1;j<=m;j++)
scanf("%d",&a[i][j]);
dfs(1,1,1);
if(flag==0)
printf("impossible\n");
return 0;
}
1 2 3 4 5 6 分别代表水管子的6种情况
详细请看这位大佬1 2 3 4 5 6 的表示什么
用dfs,从两个方面进行判断,看是不是直管子或者弯管子,这样就可以从4个方向判断进水口位置,然后用(n,m+1)判断结束,为什么是M+1,因为最后是从最右边出,所以最后肯定是(X,Y+1,1),所以就是M+1了
其他的就是用栈来储存路径,然后就是DFS模板!**
2.今天来看一下林某人口中最基本最基本的图的遍历
首先看一下无向图用dfs解决
#include<stdio.h>
int book[101],sum,n,e[101][101];
void dfs(int cur)
{
int i;
printf("%d",cur);
sum++;
if(sum==n)
return ;
for(i=1;i<=n;i++)
{
if(e[cur][i]==1&&book[i]==0)
{
book[i]=1;
dfs(i);
}
}
return ;
}
int main()
{
int i,j,m,a,b;
scanf("%d %d",&n,&m);
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
{
if(i==j)
e[i][j]=0;
else
e[i][j]=99999999;
}
for(i=1;i<=m;i++)
{
scanf("%d %d",&a,&b);
e[a][b]=1;
e[b][a]=1;
}
book[1]=1;
dfs(1);
return 0;
}
数据5 5 1 2 1 3 1 5 2 4 3 5
运行结果1 2 4 3 5
二维数组存储图
每一行就是一个点,这一行中的列就是这个点连接另一个
在解决这个问题的同时,林某人也指出了一个问题
这是一个遍历顺序,当然遍历顺序是根据代码的不同而不同,所有的遍历顺序是一个序列
当然这这就是BFS和DFS的区别
看看bfs遍历图吧
#include<stdio.h>
int book[101];
int main()
{
int e[101][101],n,m,i,j,a,cur,b;
int que[10001],head,tail;
scanf("%d %d",&n,&m);
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
{
if(i==j)
e[i][j]=0;
else
e[i][j]=99999999;
}
for(i=1;i<=m;i++)
{
scanf("%d %d",&a,&b);
e[a][b]=1;
e[b][a]=1;
}
head=1;
tail=1;
que[head]=1;
tail++;
book[1]=1;
while(head<tail&&tail<=n)
{
cur=que[head];
for(i=1;i<=n;i++)
{
if(e[cur][i]==1&&book[i]==0)
{
book[i]=1;
que[tail]=i;
tail++;
}
if(tail>n)
{
break;
}
}
head++;
}
for(i=1;i<tail;i++)
printf("%d ",que[i]);
return 0;
}
这就是bfs遍历邻接矩阵,其中序列有很多,但是本代码的搜索顺序是这样的,所以你可以有很多种方法搜索,但是需要修改其中的一些条件…
下来看看城市地图的搜索---------dfs.
首先看一下有向图
这个题,找1-5 的最短路径,并输出
直接看代码
#include<stdio.h>
int n,m,a,b,c,min=999999;
int book[101],e[101][101];
void dfs(int cur,int dis)
{
int j;
if(dis>min)
return ;
if(cur==n)
{
if(dis<min)
min=dis;
return ;
}
for(j=1;j<=n;j++)
{
if(e[cur][j]!=99999999&&book[j]==0)
{
book[j]=1;
dfs(j,dis+e[cur][j]);
book[j]=0;
}
}
return ;
}
int main()
{
int i,j;
scanf("%d %d",&n,&m);
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
{
if(i==j)
e[i][j]=0;
else
e[i][j]=99999999;
}
for(i=1;i<=m;i++)
{
scanf("%d %d %d",&a,&b,&c);
e[a][b]=c;
}
book[1]=1;
dfs(1,0);
printf("%d",min);
return 0;
}
输入的数据如下
那么问题来了,无向图的代码怎么改,只需要把邻接矩阵a[i][j]=a;a[j][i]=a
下来请看代码
#include<stdio.h>
int n,m,a,b,c,min=999999;
int book[101],e[101][101];
void dfs(int cur,int dis)
{
int j;
if(dis>min)
return ;
if(cur==n)
{
if(dis<min)
min=dis;
return ;
}
for(j=1;j<=n;j++)
{
if(e[cur][j]!=99999999&&book[j]==0)
{
book[j]=1;
dfs(j,dis+e[cur][j]);
book[j]=0;
}
}
return ;
}
int main()
{
int i,j;
scanf("%d %d",&n,&m);
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
{
if(i==j)
e[i][j]=0;
else
e[i][j]=99999999;
}
for(i=1;i<=m;i++)
{
scanf("%d %d %d",&a,&b,&c);
e[a][b]=c;
e[b][a]=c;
}
book[1]=1;
dfs(1,0);
printf("%d",min);
return 0;
}
我们可以发现这里最短路径变成了7,这是因为无向图,路径比较灵活,所以大家可以看看这个图。
好的,下面我们就看看
最少转机–图的广度优先遍历
比如这个无向图
1------ ------2
\ /
\ /|
\ / |
3 |
/ \ |
/ \ |
/ \ |
5---------4
这次我们用宽搜来写的
好了详细请看代码
#include<stdio.h>
struct f
{
int x;
int s;
};
int main()
{
int m,n,a,b,c;
int book[51]={0};
int head,tail;
struct f que[2501];
int i,j,cur,start,end,flag=0,e[51][51]={0};
head=1;
tail=1;
scanf("%d %d %d %d",&n,&m,&start,&end);
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
{
if(i==j)
e[i][j]=0;
else
e[i][j]=99999999;
}
for(i=1;i<=m;i++)
{
scanf("%d %d",&a,&b);
e[a][b]=1;
e[b][a]=1;
}
que[tail].x=start;
que[tail].s=0;
tail++;
book[start]=1;
while(head<tail)
{
cur=que[head].x;
for(j=1;j<=n;j++)
{
if(e[cur][j]!=99999999&&book[j]==0)
{
que[tail].x=j;
que[tail].s=que[head].s+1;
tail++;
book[j]=1;
}
if(que[tail-1].x==end)
{
flag=1;
break;
}
}
if(flag==1)
break;
head++;
}
printf("%d",que[tail-1].s);
return 0;
}
这便是最少转机—图的广度优先遍历
都是最基础的
大佬莫怪
好了下面就看看只有五行的算法------Floyd-Warshall
基本的图的遍历就这样,下下周再学习二叉树
下周就是最短路径----------(各种算法,动态规划!)