列表

详情


NC20907. 方格跳跃

描述

给定一个网格图,每个格子上都有一个数,初始在编号为 L 的格子上,下一次需要走到格子上的数为 (x+d) 的格子上,代价为两个格子之间的曼哈顿距离(坐标为(xi,yi)与坐标为(x_j,y_j)的两个点之间的曼哈顿距离为(|xi-xj|+|yi-yj|))。 问要走到格子上的数为 R 的格子至少需要花费多少代价。
多组测试数据。

输入描述

第一行三个整数 H,W,d,表示网格图的长度与宽度,d 的含义如题面所示。
接下来 W 行,每行 H 个整数表示网格图中每个格子的数。
下一行是一个整数 Q(1≤ Q≤105),表示询问组数。
接下来 Q 行,每行两个整数 L 和 R 代表一组询问。
保证数据合法,即不存在无法从 L 按题意跳若干步跳到 R 的数据。

输出描述

输出包含 Q 行,每行为一个整数 k,表示每一组测试数据需要花费的代价。
输出应该按照输入的顺序。

示例1

输入:

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

输出:

5

说明:

样例仅一组测试数据。
最初在位置(1,2),格子上的数为4,然后直接传送到格子上的数为6的格子,即位置(3,3),然后传送到格子(3,1)上,格子上的数为8,等于Ri了。
因此,消耗的代价为(|3-1|+|3-2|)+(|3-3|+|1-3|)=5。
数据保证0\le H,W\le 2000,\, 0\le D\le H\times W.

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++ 解法, 执行用时: 45ms, 内存消耗: 1168K, 提交时间: 2022-06-04 14:52:24

#include<bits/stdc++.h>
const int N=5e6+5;
int h,w,d,x[N],y[N],a,q,l,r;
long long s[N];
int main()
{
	scanf("%d%d%d",&h,&w,&d);
	for(int i=1;i<=h;i++)
		for(int j=1;j<=w;j++)
			scanf("%d",&a),x[a]=i,y[a]=j;
	for(int i=1;i<=h*w;i++)
		if(i>d)
			s[i]=s[i-d]+abs(x[i-d]-x[i])+abs(y[i-d]-y[i]);
	scanf("%d",&q);
	while(q--)
	{
		scanf("%d%d",&l,&r);
		printf("%lld\n",s[r]-s[l]);
	}
	return 0;
}

C++14(g++5.4) 解法, 执行用时: 46ms, 内存消耗: 1144K, 提交时间: 2019-11-22 10:29:26

#include<bits/stdc++.h>
using namespace std;

int l,r,T,H,W,d,S[4000005],w[4000005],h[4000005];
int main()
{
	int i,j,k;
	scanf("%d%d%d",&H,&W,&d);
	for(i=1;i<=H;i++)
		for(j=1;j<=W;j++)scanf("%d",&k),h[k]=i,w[k]=j;
	for(i=d+1;i<=W*H;i++)S[i]=S[i-d]+abs(w[i]-w[i-d])+abs(h[i]-h[i-d]);
	scanf("%d",&T);
	while(T--)
	{
		scanf("%d%d",&l,&r);
		printf("%d\n",S[r]-S[l]);
	}
	return 0;
}

上一题