第六次编程作业

06-图1 列出连通集   (25分)


给定一个有NNN个顶点和EEE条边的无向图,请用DFS和BFS分别列出其所有的连通集。假设顶点从0到N−1N-1N1编号。进行搜索时,假设我们总是从编号最小的顶点出发,按编号递增的顺序访问邻接点。

输入格式:

输入第1行给出2个整数NNN(0<N≤100<N\le 100<N10)和EEE,分别是图的顶点数和边数。随后EEE行,每行给出一条边的两个端点。每行中的数字之间用1空格分隔。

输出格式:

按照"{ v1v_1v1v2v_2v2 ... vkv_kvk }"的格式,每行输出一个连通集。先输出DFS的结果,再输出BFS的结果。

输入样例:

8 6
0 7
0 1
2 0
4 1
2 4
3 5

输出样例:

{ 0 1 4 2 7 }
{ 3 5 }
{ 6 }
{ 0 1 2 7 4 }
{ 3 5 }
{ 6 }


#include <stdio.h>
#include <stdlib.h>
#define MaxVertexNum 10
#define Vertex int

Vertex Check[MaxVertexNum];		//判断是否访问过该顶点 

typedef struct ENode *Edge;		//边的定义 
struct ENode{
	Vertex V1;
	Vertex V2;
};

typedef struct GNode *MGraph;	//图的定义--邻接矩阵表示 
struct GNode{
	Vertex Nv;
	Vertex Ne;
	Vertex G[MaxVertexNum][MaxVertexNum];
};

MGraph CreateGraph(int);
MGraph BuildGraph(MGraph ,int);
void Insert(MGraph, Edge);
void InitializeArray(int);
void PrintUnion(MGraph);
void Visited(Vertex);
void TraverseDFS(MGraph,Vertex);

int main()
{
	int N, E;
	MGraph Graph;
	
	scanf("%d %d", &N, &E);
	Graph = CreateGraph(N);
	Graph = BuildGraph(Graph ,E);
	InitializeArray(N);
	PrintUnion(Graph);
}

//建立一个空图 
MGraph CreateGraph(int N)
{
	int i, j;
	
	MGraph Graph = (MGraph)malloc(sizeof(struct GNode));
	Graph->Nv = N;
	for(i = 0; i < N; i++)
		for(j = 0; j < N; j++)
			Graph->G[i][j] = 0;
	
	return Graph;		
}

//建立完整的图 
MGraph BuildGraph(MGraph Graph,int edge)
{
	int i;
	
	Edge E = (Edge)malloc(sizeof(struct ENode));
	for(i = 0; i < edge; i++){
		scanf("%d %d", &E->V1, &E->V2);
		Insert(Graph, E);
	}
	
	return Graph;
}

//将每一条输入的边存入图 
void Insert(MGraph Graph, Edge E)
{
	Graph->G[E->V1][E->V2] = E->V2;
	Graph->G[E->V2][E->V1] = E->V1;
}

//初始化判断数组 
void InitializeArray(int N)
{
	int i;
	
	for(i = 0; i < N; i++)
		Check[i] = 0;
}

void Visited(Vertex V)
{
	Check[V] = 1;
}

//打印连通集 
void PrintUnion(MGraph Graph)
{
	int i;
	
	//对于0到n-1顶点的每一行进行遍历 
	for(i = 0; i < Graph->Nv; i++){
		if(!Check[i]){
			printf("{ ");
			TraverseDFS(Graph ,i);
			printf("}\n");
		}
	}
}

//深度优先搜索 
void TraverseDFS(MGraph Graph ,Vertex V)
{	
	int i;
	
	Visited(V);
	printf("%d ", V);
	
	//对第V行的每个元素进行遍历 
	//如果未被遍历过,并且V i是一条边的话, 跳到第i行进行深入遍历 
	for(i = 0; i < Graph->Nv; i++){
		if(Graph->G[V][i] && !Check[i]){
			TraverseDFS(Graph, i);
		}
	}
}


#include <stdio.h>
#include <stdlib.h>
#define MaxVertexNum 10
#define Vertex int

Vertex Check[MaxVertexNum];		//用来判断顶点是否访问过 
	
typedef struct ENode *Edge;		//边 
struct ENode{
	Vertex V1;
	Vertex V2;
};

typedef struct GNode *MGraph;		//图的定义--邻接矩阵 
struct GNode{
	Vertex Nv;
	Vertex Ne;
	Vertex G[MaxVertexNum][MaxVertexNum];
};

typedef struct VNode *PtrToVNode;	//存入队列的数据结构 
struct VNode{
	Vertex Data;
	PtrToVNode Next;
};

typedef struct QNode *Queue;		//队列 
struct QNode{
	PtrToVNode Front;
	PtrToVNode Rear;
};

MGraph CreateGraph(int);
MGraph BuildGraph(MGraph ,int);
void Insert(MGraph, Edge);
void InitializeArray(int);
void PrintUnion(MGraph);
void Visited(Vertex);
void TraverseBFS(MGraph ,Vertex);
Queue CreateQueue();
void EnQueue(Queue, Vertex);
int IsEmpty(Queue);
Vertex DeleteQueue(Queue);

int main()
{
	int N, E;
	MGraph Graph;
	
	scanf("%d %d", &N, &E);
	Graph = CreateGraph(N);
	Graph = BuildGraph(Graph ,E);
	InitializeArray(N);
	PrintUnion(Graph);
}

//建立空图,每个数据设为0 
MGraph CreateGraph(int N)
{
	int i, j;
	
	MGraph Graph = (MGraph)malloc(sizeof(struct GNode));
	Graph->Nv = N;
	for(i = 0; i < N; i++)
		for(j = 0; j < N; j++)
			Graph->G[i][j] = 0;
	
	return Graph;		
}

//建立完整的图--邻接矩阵表示法 
MGraph BuildGraph(MGraph Graph,int edge)
{
	int i;
	
	Edge E = (Edge)malloc(sizeof(struct ENode));
	for(i = 0; i < edge; i++){
		scanf("%d %d", &E->V1, &E->V2);
		Insert(Graph, E);
	}
	
	return Graph;
}

//将边插入图中(将数据放入图),这里是无向图 
void Insert(MGraph Graph, Edge E)
{
	Graph->G[E->V1][E->V2] = E->V2;
	Graph->G[E->V2][E->V1] = E->V1;
}

//初始化用来判断是否访问过的数组 
void InitializeArray(int N)
{
	int i;
	
	for(i = 0; i < N; i++)
		Check[i] = 0;
}

//第一次遍历的顶点设为访问过, 并输出 
void Visited(Vertex V)
{
	Check[V] = 1;
	printf("%d ", V);
}

//打印连通集 
void PrintUnion(MGraph Graph)
{
	int i;
	
	//遍历0到N-1的未访问过的顶点 
	for(i = 0; i < Graph->Nv; i++){
		if(!Check[i]){
			printf("{ ");
			TraverseBFS(Graph ,i);
			printf("}\n");
		}
	}
}

//广度优先搜索 
void TraverseBFS(MGraph Graph ,Vertex V)
{
	Vertex D, W;
	
	Queue Q = CreateQueue();
	Visited(V);
	EnQueue(Q, V);
	
	while(!IsEmpty(Q)){
		D = DeleteQueue(Q);
		for(W = 0; W < Graph->Nv; W++){
			//顶点W没有被访问过, ***并且W和V能构成一条边*** 
			if(!Check[W] && Graph->G[D][W]){
				Visited(W);
				EnQueue(Q, W);
			}
		}
	}
	free(Q->Front);
	free(Q);
}

//创建一个空队列,头尾指针指向队列首位元素之前的位置
//并且当且仅当 头尾指针相等时, 队列为空 
Queue CreateQueue()
{
	Queue Q = (Queue)malloc(sizeof(struct QNode));
	//创建一个队列首位元素位置之前的结点
	//队列首尾指针同时指向它 
	PtrToVNode S = (PtrToVNode)malloc(sizeof(struct VNode));
	S->Data = -1;
	S->Next = NULL;
	Q->Front = Q->Rear = S;
	
	return Q;
}

void EnQueue(Queue Q, Vertex V)
{
	//入队时,头指针不动,尾指针向后挪一位 
	PtrToVNode S = (PtrToVNode)malloc(sizeof(struct VNode));
	S->Data = V;
	S->Next = NULL;
	Q->Rear->Next = S;
	Q->Rear = Q->Rear->Next;
}

//判断队列是否为空 
int IsEmpty(Queue Q) 
{
	return Q->Rear == Q->Front;
}

//删除队列的首元素 , 并返回其值 
Vertex DeleteQueue(Queue Q)
{
	Vertex D;
	PtrToVNode Temp;
 
	D = Q->Front->Next->Data;	//头指针的下一位才是首元素 
	Temp = Q->Front;
	Q->Front = Q->Front->Next;	 //头指针往后挪, ****记住首元素是头指针的next的位置 *** 
	free(Temp);
	
	return D;
}


06-图2 Saving James Bond - Easy Version   (25分)


This time let us consider the situation in the movie "Live and Let Die" in which James Bond, the world's most famous spy, was captured by a group of drug dealers. He was sent to a small piece of land at the center of a lake filled with crocodiles. There he performed the most daring action to escape -- he jumped onto the head of the nearest crocodile! Before the animal realized what was happening, James jumped again onto the next big head... Finally he reached the bank before the last crocodile could bite him (actually the stunt man was caught by the big mouth and barely escaped with his extra thick boot).

Assume that the lake is a 100 by 100 square one. Assume that the center of the lake is at (0,0) and the northeast corner at (50,50). The central island is a disk centered at (0,0) with the diameter of 15. A number of crocodiles are in the lake at various positions. Given the coordinates of each crocodile and the distance that James could jump, you must tell him whether or not he can escape.

Input Specification:

Each input file contains one test case. Each case starts with a line containing two positive integers NNN (≤100\le 100100), the number of crocodiles, and DDD, the maximum distance that James could jump. Then NNN lines follow, each containing the (x,y)(x, y)(x,y) location of a crocodile. Note that no two crocodiles are staying at the same position.

Output Specification:

For each test case, print in a line "Yes" if James can escape, or "No" if not.

Sample Input 1:

14 20
25 -15
-25 28
8 49
29 15
-35 -2
5 28
27 -29
-8 -28
-20 -35
-25 -20
-13 29
-30 15
-35 40
12 12

Sample Output 1:

Yes

Sample Input 2:

4 13
-12 12
12 12
-12 -12
12 -12

Sample Output 2:

No


#include <stdio.h>
#include <math.h>

#define MAXSIZE 101
#define Center_Dis 15

typedef struct Node VNode;	 
struct Node{
	int x;
	int y;
};
VNode croro[MAXSIZE];		//存数据的结构数组 
int Visited[MAXSIZE];		//踩过的鳄鱼 

void Initialize(VNode [], int [], int);
void Travel(int, int);
int DFS(int, int, int);
int Jump_Safe(int, int, int);
int IsSave(int, int);

int main()
{
	int N, D;
	
	scanf("%d %d", &N, &D);
	Initialize(croro, Visited, N);
	Travel(N, D);
	
	return 0;
}

//初始化结构数组 
void Initialize(VNode croro[], int Visited[], int N)
{
	int i;
	
	for(i = 0; i < N; i++){
		scanf("%d %d", &croro[i].x, &croro[i].y);
		Visited[i] = 0;
	}	
}

//开始遍历鳄鱼 
void Travel(int N, int D)
{
	int i;
	int a, b;
	int answer = 0;
	int FirstNode[N];

	//FirstNode[]存放鳄鱼到中心点的距离 
	for(i = 0; i < N; i++){
		a = croro[i].x * croro[i].x;
		b = croro[i].y * croro[i].y;
		FirstNode[i] = sqrt(a+b); 
	} 
	
	//遍历没有被踩过的并且距离岛半径D之内的鳄鱼 
	for(i = 0; i < N; i++){
		if(!Visited[i] && (FirstNode[i]-Center_Dis) <= D){
			answer = DFS(i ,N, D);
			if(answer){
				break;
			}
		}
	}
	if(answer){
		printf("Yes");
	}
	else{
		printf("No");
	}
}

int DFS(int V, int N, int D)
{
	int answer = 0;
	int i, W;
	
	Visited[V] = 1;		//更新正访问的点 
	if(IsSave(V, D)){		//下一跳是否可以上岸 
		answer = 1;
	}
	//从V点跳到其它未被访问的点W,V到W的距离在半径D之内 
	else{
		for(W = 0; W < N; W++){
			if(!Visited[W] && Jump_Safe(V, W, D)){
				answer = DFS(W, N, D);
				if(answer){
					break;
				}
			}
		}
	}	
	
	return answer;
}

int IsSave(int V, int D)
{	
	int a, b;
	
	a = fabs(croro[V].x);
	b = fabs(croro[V].y);
	if((a+D) >=50 || (b+D) >= 50){
		return 1;
	}
	else{
		return 0;
	}
}

int Jump_Safe(int V, int W, int D)
{
	int a, b, d;
	
	a = (croro[V].x - croro[W].x) * (croro[V].x - croro[W].x); 
	b = (croro[V].y - croro[W].y) * (croro[V].y - croro[W].y); 
	d = sqrt(a+b);
	
	return d <= D;
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值