solution-p4955

题解 P4955 【[USACO14JAN]Cross Country Skiing S】

原题

翻译,从学校OJ偷来的

乍一看,要求最小的难度值D,于是考虑二分答案 + bfs/dfs。

如果一个关键格\((x,y)\)能够到达关键格\((xi,yi)\)\((xj , yj)\)

那么\((xi,yi)\)也能通过\((x,y)\)到达\((xj,yj)\),反之亦然。

所以只要验证:

\((x,y)\)是否能够到达所有其他关键格即可。

代码

时间复杂度\(O(NMlog\;a[i][j])\)

// 此处应有头文件 
using namespace std;
const int N = 5e2 + 10;
int n,m;
int a[N][N]; // 存地图 
bool vis[N][N]; // 是否访问过 
int fsum = 0; // 关键格数量 
bool f[N][N]; // 是否为关键格 
struct node
{
	int x,y;
};
int dx[] = {0 , 0 , -1 , 1};
int dy[] = {-1 , 1 , 0 , 0}; // 移动 
int sx,sy; // 存其中一个关键格的位置 
bool bfs(int k)
{
	memset( vis , false , sizeof(vis) );
	queue<node> q; 
	q.push( (node){sx , sy} );
	vis[sx][sy] = true;
	int sum = 0; // 已经访问到多少个关键格 
	while( !q.empty() )
	{
		node t = q.front();
		q.pop();
		if( f[t.x][t.y] )
			++sum;
		if(sum >= fsum)
			return true;
		for(int i = 0;i < 4;i++)
		{
			int xx = t.x + dx[i];
			int yy = t.y + dy[i];
			if( xx > 0 && yy > 0 && xx <= n && yy <= m && !vis[xx][yy] )
			{
				if( abs( a[t.x][t.y] - a[xx][yy] ) <= k )
				{
					q.push( (node){xx , yy} );
					vis[xx][yy] = true;
				}
			}
		}
	}
	return false;
}
bool check(int k)
{
	if( !bfs(k) )
		return false;
	return true;
}
int main()
{
	int l = 0;
	int r = 0;
	cin >> n >> m;
	for(int i = 1;i <= n;i++)
		for(int j = 1;j <= m;j++)
		{
			cin >> a[i][j];
			r = max(a[i][j] , r); // 取全地图的最高点作为右界限 
		}	
	for(int i = 1;i <= n;i++)
		for(int j = 1;j <= m;j++)
		{
			cin >> f[i][j];
			if( f[i][j] )
			{
				++fsum;
				sx = i,sy = j; // 存其中一个关键格的位置 
			}
		}
	while(l < r) // 二分答案 
	{
		int mid = l + r >> 1; // 右移一位 = /2 
		if( check(mid) )
			r = mid;
		else
			l = mid + 1;
	}
	cout << l << endl;
    return 0;
}
posted @ 2024-03-06 16:55  iorit  阅读(6)  评论(0)    收藏  举报