【数据结构】图

1.1定义
图(Graph)结构是一种非线性的数据结构。
由一组顶点和一组能够将两个顶点相连的边组成的。
1.2.存储结构
存储结构分两种 一种是邻接矩阵(二维数组)另一种是邻接表
1.2.1邻接矩阵
二维数组索引的值表示顶点 二维数组存储的值表示是否连接 若连接 则存储1 否则存储0

2图的遍历

2.1深度优先遍历
2.1.1例题
P1135 奇怪的电梯
在这里插入图片描述

输入格式
共二行。

第一行为33个用空格隔开的正整数,表示N,A,B(1≤N≤200, 1≤A,B≤N)N,A,B(1≤N≤200,1≤A,B≤N)。

第二行为NN个用空格隔开的非负整数,表示K_iK
i

输出格式
一行,即最少按键次数,若无法到达,则输出-1−1。

输入输出样例
输入 #1复制
5 1 5
3 3 1 2 5
输出 #1复制
3

#include<stdio.h>
int x,y,cnt,m=10000,i,book[1010],a[1010],n,ans;
void dfs(int c)
{
	if(cnt>=m)
	return;
	if(c==y)
	{
		m=cnt;
		return;
	}
	book[c]=1;
	cnt++;
	if(c+a[c]<=n&&book[c+a[c]]==0)
		dfs(c+a[c]);
	if(c-a[c]>=1&&book[c-a[c]]==0)
		dfs(c-a[c]);
	cnt--;
	book[c]=0;
} 
int main()
{
	while(scanf("%d",&n)!=EOF)
	{
		if(n==0)
		return 0;
		scanf("%d %d",&x,&y);
		for(i=1;i<=n;i++)
			scanf("%d",&a[i]);
		dfs(x);
		if(m==10000)
			printf("-1\n");
		else
			printf("%d\n",m);}
}

2.1.2例题
题目描述*:小哼走迷宫,从(startx,starty)到(p,q) 求最短路径的步数step

#include<stdio.h>
int min=9999999;
int m,n,p,q;
int book[10][10];
int a[101][101];
void dfs(int x,int y,int step)
{
	int dir[4][2]={{0,1},{1,0},{0,-1},{-1,0}};
	int tx,ty,k;
	if(x==p&&y==q)
	{
		if(step<min)
		{
		//printf("hh");
		min=step;
		} 
		return;
	    
	}
	for(k=0;k<4;k++)
	{
	//	printf("hh");
		int tx=x+dir[k][0];
		int ty=y+dir[k][1];
		if(tx<1||tx>n||ty<1||ty>m)
		continue; 
		if(book[tx][ty]==0&&a[tx][ty]==0)
		{
			//printf("hh");
			book[tx][ty]=1;
			dfs(tx,ty,step+1);
			book[tx][ty]=0;
		}
			
	}
	return ;
	
 } 
int main()
{
	int sx,sy,i,j;
	scanf("%d %d",&n,&m);
	for(i=1;i<=n;i++)
		for(j=1;j<=m;j++)
			scanf("%d",&a[i][j]);
	scanf("%d %d %d %d",&sx,&sy,&p,&q);
	book[sx][sy]=1;
	dfs(sx,sy,0);
	printf("%d",min); 
			
}

2.1.3例题
题目描述:炸弹放在哪里可以消灭最多的敌人(炸弹杀伤距离超长)
题目解析:从放炸弹的起始点开始遍历右下左上走的每个点可以消灭的敌人数,找出最大的即可
代码实现

#include<stdio.h>
int max,sum,mx,my,k,n,m,book[101][101]={0};
char a[101][101];
int Sum(int i,int j)
{
    int sum,x,y;
    sum=0;
    x=i,y=j;
    while(a[x][y]!='#')//#代表墙
    {
        if(a[x][y]=='G')//G代表敌人
        sum++;
        x--;//向上统计
    }
    x=i,y=j;
    while(a[x][y]!='#')//#代表墙
    {
        if(a[x][y]=='G')//G代表敌人
        sum++;
        x++;//向下统计
    }
    x=i,y=j;
    while(a[x][y]!='#')//#代表墙
    {
        if(a[x][y]=='G')//G代表敌人
        sum++;
        y--;//向左统计
    }
    x=i,y=j;
    while(a[x][y]!='#')//#代表墙
    {
        if(a[x][y]=='G')//G代表敌人
        sum++;
        y++;//向右统计
    }
    return sum;
}
void dfs(int x,int y)
{
	int next[4][2]={{0,1},{1,0},{0,-1},{-1,0}};
	sum=Sum(x,y);
	if(sum>max)
	{
		max=sum;
		mx=x;
		my=y;
		
	}
	for(k=0;k<4;k++)
	{
		int tx=x+next[k][0];
		int ty=y+next[k][1];
		if(tx<1||tx>n-1||ty<1||ty>m-1)
			continue;
		if(book[tx][ty]==0&&a[tx][ty]=='.')
		{
			book[tx][ty]=1;
			dfs(tx,ty);
		}
		return ;
}
}
int main()
{
	int i,j,k,tx,ty;
    int head,tail,startx,starty;
    scanf("%d %d %d %d",&m,&n,&startx,&starty);
    for(i=0;i<n;i++)
        scanf("%s",a[i]);
        book[tx][ty]=1;
    max=Sum(startx,starty);
    dfs(startx,starty);
    printf("%d",max);
    getchar();
}

2.3广度优先遍历
2.3.1题目描述:小哼走迷宫,从(startx,starty)到(p,q) 求最短路径的步数step
题目解析
队列存储坐标再搜素队列中的坐标

#include<stdio.h>
#include<string.h>
struct note
{
    int x;
    int y;
    int s;
    int f;
};
int main()
{
	struct note que[201];
    int a[101][101]={0},book[10][10]={0};
    int next[4][2]={{0,1},{1,0},{0,-1},{-1,0}};
    int head,tail;
    int startx,starty,m,n,p,q,tx,ty,flag,i,j,k;
    scanf("%d %d",&n,&m);
    for(i=1;i<=n;i++)
        for(j=1;j<=m;j++)
            scanf("%d",&a[i][j]);
    scanf("%d %d %d %d",&startx,&starty,&p,&q);
    head=1;
    tail=1;
    que[tail].x=startx;
    que[tail].y=starty;
    que[tail].f=0;
    que[tail].s=0;
    tail++;
    book[startx][starty]=1;
    flag=0;   
    while(head<tail)
    {
        for(k=0;k<=3;k++)
        {
            tx=que[head].x+next[k][0];
            ty=que[head].y+next[k][1];
            if(tx<1||tx>n||ty<1||ty>m)
            	continue;
            if(a[tx][ty]==0&&book[tx][ty]==0)
            {
                book[tx][ty]=1;
                que[tail].x=tx;
                que[tail].y=ty;
                que[tail].f=head;
                que[tail].s=que[head].s+1;
                tail++;
            }
            if(tx==p&&ty==q)
            {
            //	printf("hh");
                flag=1;
                break;
            }
            
        }
        if(flag==1)
        	break;
        head++;
    }
    printf("%d",que[tail-1].s);
    getchar();
    getchar();
}      

2.3.2 炸弹人
题目描述:炸弹放在哪里可以消灭最多的敌人(炸弹杀伤距离超长)
题目解析:从放炸弹的起始点开始遍历右下左上走的每个点可以消灭的敌人数,找出最大的即可
代码实现

#include<stdio.h>
char a[101][101];
struct note
{
	int x;
    int y;
    int s;
}que[101];
int Sum(int i,int j)
{
    int sum,x,y;
    sum=0;
    x=i,y=j;
    while(a[x][y]!='#')//#代表墙
    {
        if(a[x][y]=='G')//G代表敌人
        sum++;
        x--;//向上统计
    }
    x=i,y=j;
    while(a[x][y]!='#')//#代表墙
    {
        if(a[x][y]=='G')//G代表敌人
        sum++;
        x++;//向下统计
    }
    x=i,y=j;
    while(a[x][y]!='#')//#代表墙
    {
        if(a[x][y]=='G')//G代表敌人
        sum++;
        y--;//向左统计
    }
    x=i,y=j;
    while(a[x][y]!='#')//#代表墙
    {
        if(a[x][y]=='G')//G代表敌人
        sum++;
        y++;//向右统计
    }
    return sum;
}
int main()
{
    int n,m,i,j,k,tx,ty,sum,max=0,mx,my;
    int next[4][2]={{0,1},{1,0},{0,-1},{-1,0}};
    int head,tail,startx,starty,book[101][101]={0};
    scanf("%d %d %d %d",&m,&n,&startx,&starty);
    for(i=0;i<n;i++)
        scanf("%s",a[i]);
    head=1;
    tail=1;
    que[tail].x=startx;
    que[tail].y=starty;
    que[tail].s=0;
    tail++;
    book[startx][starty]=1;
    max=Sum(startx,starty);
    mx=startx;
    my=starty;
    while(head<tail)
    {
        for(k=0;k<4;k++)
        {
            tx=que[head].x+next[k][0];
            ty=que[head].y+next[k][1];
            if(tx<1||tx>n-1||ty>1||ty>m-1)
                continue;
            if(book[tx][ty]==0&&a[tx][ty]=='.')
            {
                book[tx][ty]=1;
                que[tail].x=tx;
                que[tail].y=ty;
                tail++;
                sum=Sum(tx,ty);
                if(sum>max)
                {
                    max=sum;
                    mx=tx;
                    my=ty;
                }
            }
        }
        head++;
    }
    printf("%d %d",mx,my);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值