越野滑雪(skiing)

题目描述

乡村越野滑雪比赛在一个m×n(1<=m,n<=500)的二维表格中进行,每个格子的海拔在[0,1000000000]之间。滑雪者可以从一个格子滑到相邻格子,(可以从高处滑到低处,也可以从低处滑到高处),两者之间的海拔差的绝对值为其难度值。相邻的格子是指有公共边的格子。一条路径的难度值是指该路径上途经相邻两格子的难度值的最大值。现在给出若干个关键格子,求所有这些关键格子相互可达的最小的难度值。

输入格式:

第一行包含两个整数M、N。
接下来M行,每行包含N个海拔值。
再接下来M行,每行N个数,为1则表示该格子为关键格子。
输出格式:
一个数,表示关键格子相互可达的最小的难度值。

输入样例:

3 5
20 21 18 99 5
19 22 20 16 26
18 17 40 60 80
1 0 0 0 1
0 0 0 0 0
0 0 0 0 1

输出样例:

21

题解:

STD是用的最小生成树
将格子看做点,将相邻的格子之间的难度系数看做边权,得到一个无向图。
然后求包含给出的关键点的最小生成树.此处的最小生成树不是对边求和,而是找边的最大值。
对每个连通块记录其中包含的关键点的个数。当某个连通块包含的关键点数等于最大值了,那么此时就可以退出程序了。

但是!!!
生成树什么的完全没有必要!!!
我们可以直接从一个关键点出发,BFS求它到每个点的最短(最小难度值)路径,再输出它们的最大值。
其它点间的的路径?No need!!!

若有3个关键点A,B,C,其中A到B、C的路径难度值最小分别为x、y
而B->C的可由B->A再A->C,
该线路的最大难度值为max(x,y)
那么B到C的最小难度值一定不会超过x、y的最大值

BFS还蛮好写的,就不再详述了

PS:考试的时候大概想了10分钟,花20分钟写了个大概框架
添加变量,输入样例数据,准备调试
TMD样例居然就过了???
胆战心惊地检查了半天,果然有问题
难度最大值没有入队
那我TM是怎么过的???
唉交吧交吧

爆零…
果然还是有问题
提交至网上测评,运行错误
唉慢着这内存不对呀 难道数组开大了
重新提交
AC…

妈的

最后附上丑陋的代码

#include<iostream>
#include<cstdio>
#define maxp 501
#define maxn 5000001 
using namespace std;
int n,m,x1,y1,z1,x2,y2,z2;
int map[maxp][maxp];
int dp[maxp][maxp];
int que[maxn][3],head,tail;
int key[maxp*maxp][2],k,ans;
int zheng(int a)
{
	if(a<0)return -a;
	else return a;
}
int main()
{

	scanf("%d%d",&m,&n);
	for(int i=1;i<=m;i++)
	for(int j=1;j<=n;j++)
	{
		scanf("%d",&map[i][j]);
		dp[i][j]=1000000002;
	}
	for(int i=1;i<=m;i++)
	for(int j=1;j<=n;j++)
	{
		scanf("%d",&key[k][0]);
		if(key[k][0])
		{
			key[k][0]=i;
			key[k][1]=j;
			k++;
		}
	}
	que[tail][0]=key[0][0];
	que[tail][1]=key[0][1];
	tail++;
	while(head!=tail)
	{
		x2=x1=que[head][0];
		y2=y1=que[head][1];
		z1=que[head][2];
		x2++;
		if(x2<=m)
		{
			z2=max(z1,zheng(map[x1][y1]-map[x2][y2]));
			if(dp[x2][y2]>z2)
			{
				dp[x2][y2]=z2;
				que[tail][0]=x2;
				que[tail][1]=y2;
				que[tail][2]=z2;
				tail++;
				if(tail==maxn)
					tail=0;
			}
		}
		x2-=2;
		if(x2>0)
		{
			z2=max(z1,zheng(map[x1][y1]-map[x2][y2]));
			if(dp[x2][y2]>z2)
			{
				dp[x2][y2]=z2;
				que[tail][0]=x2;
				que[tail][1]=y2;
				que[tail][2]=z2;
				tail++;
				if(tail==maxn)
					tail=0;
			}
		}
		x2++;
		y2++;
		if(y2<=n)
		{
			z2=max(z1,zheng(map[x1][y1]-map[x2][y2]));
			
			if(dp[x2][y2]>z2)
			{
				dp[x2][y2]=z2;
				que[tail][0]=x2;
				que[tail][1]=y2;
				que[tail][2]=z2;
				tail++;
				if(tail==maxn)
					tail=0;
			}
		}
		y2-=2;
		if(y2>0)
		{
			z2=max(z1,zheng(map[x1][y1]-map[x2][y2]));
			if(dp[x2][y2]>z2)
			{
				dp[x2][y2]=z2;
				que[tail][0]=x2;
				que[tail][1]=y2;
				que[tail][2]=z2;
				tail++;
				if(tail==maxn)
					tail=0;
			}
		}
		head++;
	}
	for(int i=1;i<=k;i++)
	{
		if(ans<dp[key[i][0]][key[i][1]])
		ans=dp[key[i][0]][key[i][1]];
	}
	cout<<ans;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值