数据结构暑期自学--MOOC浙江大学pta(7-11 Saving James Bond - Hard Version)

题目链接

前言:

这题细节真的有很多,真的很讨厌。

关键点:

1、本题与上题(easy)的不同点,该题要求的是007逃出岛的路径,因此要用到无权图单源最短路算法:

/* 邻接表存储 - 无权图的单源最短路算法 */

/* dist[]和path[]全部初始化为-1 */
void Unweighted ( LGraph Graph, int dist[], int path[], Vertex S )
{
    Queue Q;
    Vertex V;
    PtrToAdjVNode W;
    
    Q = CreateQueue( Graph->Nv ); /* 创建空队列, MaxSize为外部定义的常数 */
    dist[S] = 0; /* 初始化源点 */
    AddQ (Q, S);

    while( !IsEmpty(Q) ){
        V = DeleteQ(Q);
        for ( W=Graph->G[V].FirstEdge; W; W=W->Next ) /* 对V的每个邻接点W->AdjV */
            if ( dist[W->AdjV]==-1 ) { /* 若W->AdjV未被访问过 */
                dist[W->AdjV] = dist[V]+1; /* W->AdjV到S的距离更新 */
                path[W->AdjV] = V; /* 将V记录在S到W->AdjV的路径上 */
                AddQ(Q, W->AdjV);
            }
    } /* while结束*/
}

2、细节一:题目说的:

 If there are many shortest paths, just output the one with the minimum first jump, which is guaranteed to be unique.

 说明有可能有多条路径均为最短,那么就输出第一次从岛上跳到鳄鱼上最短的一条。

看到这里,我第一个想法是将所以最短的都存起来,后面判断,但是很快这种方法非常不好,最好在一开始就从最短的可以跳到鳄鱼上的路径开始选择,因此我修改了firstjump这个函数,让其既可以判断是否可以跳上鳄鱼,也可以返回长度,方便后序进行排序

int firstjump(int x)
{
	double ju = sqrt(g[x][1]*g[x][1]+g[x][2]*g[x][2]);
	if (ju<=7.5+d)
	return ju;
	else
	return 0;
}

3、细节二:如何输出path:

很明显,递归是好想好写的

void findpath(int x, int start)
{
	if (x==start)
	{
		printf("%d %d\n", g[start][1], g[start][2]);
		return ;
	}
	findpath(path[x], start);
	printf("%d %d\n", g[x][1], g[x][2]);
} 

一直遍历start存的是第一次跳到鳄鱼的编号,因为输出样例是从第一只鳄鱼开始输出的,因此一直不断递归,指导递归到start,再分别输出。

4、细节三:

在写完整体代码提交后,很讨厌的是竟然还要排除鳄鱼在岛上,或在岸上的情况。

再写一个函数来判断:

int pan(int x, int y)
{
	double ju = sqrt(x*x+y*y);
//	printf("%f\n", ju);
	if (ju<=7.5)
	return 0;
	if (x<=-50||x>=50||y<=-50||y>=50)
	return 0;
	return 1;
}

先根据距离来判断是否在岛上,再根据坐标判断是否在岸上。

5、细节五:考虑007腿超长,可以一脚就上岸边,

直接在开头判断

	scanf("%d%d", &n, &d);
	if (d>=50)
	{
		printf("1\n");
		return 0;
	}

真的是有很多细节啊,改的我,哎。

完整代码

# include <stdio.h>
# include <stdlib.h>
# include <math.h> 
# include <string.h>
# include <algorithm>
using namespace std;
int n, d;
int g[200][3];
int dist[200];
int path[200];
int pos;
int level, num;
struct Canjump{
	int pos;
	int dis;
}canjump[200];
bool cmp(Canjump j1, Canjump j2)
{
	return j1.dis<j2.dis;
}
typedef struct queue *Queue;
struct queue{
	int *data;
	int front, rear;
};
Queue createQueue(int size)
{
	Queue Q = (Queue)malloc(sizeof(struct queue));
	Q->data = (int *)malloc(sizeof(int)*size);
	Q->front = -1;
	Q->rear = -1; 
	return Q;
}
void AddQ(Queue Q, int x)
{
	Q->data[++Q->rear] = x;
}
int DeleteQ(Queue Q)
{
	return Q->data[++Q->front];
}
int IsEmpty(Queue Q)
{
	if (Q->front == Q->rear)
	return 1;
	else
	return 0;
}
int firstjump(int x)
{
	double ju = sqrt(g[x][1]*g[x][1]+g[x][2]*g[x][2]);
	if (ju<=7.5+d)
	return ju;
	else
	return 0;
}
int issave(int x)
{
	if ((g[x][1]-d<=-50)||(g[x][1]+d)>=50||(g[x][2]-d<=-50)||(g[x][2]+d)>=50)
	return 1;
	else
	return 0;
}
int pan(int x, int y)
{
	double ju = sqrt(x*x+y*y);
	if (ju<=7.5)
	return 0;
	if (x<=-50||x>=50||y<=-50||y>=50)
	return 0;
	return 1;
}
int jump(int x, int y)
{
	double ju = sqrt((g[x][1]-g[y][1])*(g[x][1]-g[y][1])+(g[x][2]-g[y][2])*(g[x][2]-g[y][2]));
	if (ju<=d)
	return 1;
	else
	return 0;
}
int find(int x)
{
	Queue Q;
	Q = createQueue(200);
	AddQ(Q, x);
	int answer = 0;
	
	dist[x] = 0;
	while (!IsEmpty(Q))
	{
		int V = DeleteQ(Q);
		if (issave(V))
		return V;
		for (int i=1; i<=num; i++)
		{
			if (dist[i]==-1&&jump(i, V))
			{
				dist[i] = dist[V]+1;
				path[i] = V;
				AddQ(Q, i);
			}
		}
	}
	return answer;
}
void findpath(int x, int start)
{
	if (x==start)
	{
		printf("%d %d\n", g[start][1], g[start][2]);
		return ;
	}
	findpath(path[x], start);
	printf("%d %d\n", g[x][1], g[x][2]);
} 
int main()
{
	scanf("%d%d", &n, &d);
	if (d>=50)
	{
		printf("1\n");
		return 0;
	}
	for (int i=1; i<=n; i++)
	{
		int x, y;
		scanf("%d%d", &x, &y);
		if (pan(x, y))
		{
			num++;
			g[num][1] = x;
			g[num][2] = y;
		}
	}
	for (int i=1; i<=num; i++)
	{
		int x = firstjump(i);
		if (x)
		{
			++pos;
			canjump[pos].pos = i;
			canjump[pos].dis = x;
		}
	} 
	sort(canjump+1, canjump+1+pos, cmp);
	int i;
	for (i=1; i<=pos; i++)
	{
		memset(dist, -1, sizeof(dist));
		memset(path, -1, sizeof(path));
		int x = find(canjump[i].pos);
		if (x!=0)
		{
			printf("%d\n", dist[x]+=2);
			findpath(x, canjump[i].pos);
			break;
		}
	}
	if (i==pos+1)
	printf("0");
	return 0;
} 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值