noip模拟题(越野滑雪)

                                   noip模拟题(越野滑雪题目描述

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

输入
第1行:2个整数M和N
接下来M行,每行N个整数,表示各网格的高度
接下来M行,每行N个0或者1,1表示关键网格
输出
第1行:1个整数,表示最小的D
样例输入 Copy
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
样例输出 Copy
21
刚接到这道题的时候觉得这道题肯定用dp,但是我dp基本不会,所以最后这道题骗了一个样例分。
std正解:将格子看成点,将相邻的格子之间的难度系数看作边权,得到一个无向图。然后求包含给出的关键点的最小生成树,此处求最小生成树不是对边求和,而是找边的最大值。
如何知道关键点都已经连通了呢?可以对每个连通块记录其中包含的关键点的个数。当某个连通块包含的关键点个数等于最大值了,那么此时就可以退出程序了。

但我认为这样建图太过麻烦,我们老大旭哥,用bfs进行访问,也将题目ac了,我用的二分答案,
对mid进行判断,进行深搜访问,虽然时间慢了点,但还是ac了。下面献上垃圾代码一份,各位大神有其他解决方案的,献上代码。

#include
#define smax 501
using namespace std;
int n,m,mmap[smax][smax];
int dir[4][2]={{0,-1},{0,1},{1,0},{-1,0}},num,cnt;
int l,r,mid,vis[smax][smax],x,y,guan[smax][smax];
void sou(int x,int y)
{
	vis[x][y]=1;
	if(guan[x][y]) cnt++;
	for(int i=0;i<4;i++)
	{
		if(x+dir[i][0]>=1&&x+dir[i][0]<=n&&y+dir[i][1]>=1&&y+dir[i][1]<=m&&!vis[x+dir[i][0]][y+dir[i][1]])
		{
			if(abs(mmap[x+dir[i][0]][y+dir[i][1]]-mmap[x][y])<=mid)
			{
				sou(x+dir[i][0],y+dir[i][1]); 
			}
		}
	}
}
bool check()
{
	cnt=0;
	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++)
		{
			vis[i][j]=0;
		}
	sou(x,y);
	return num==cnt;
}
int main()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++)
		{
			scanf("%d",&mmap[i][j]);
			if(i>1) r=max(r,abs(mmap[i][j]-mmap[i-1][j]));
			if(j>1) r=max(r,abs(mmap[i][j]-mmap[i][j-1]));
		}
	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++)
		{
			scanf("%d",&guan[i][j]);
			if(guan[i][j])
			{
				x=i;y=j;num++;
			}
		}
	while(l

你可能感兴趣的:(noip,c++)