多维线段树 Jumping Haybales

Gym - 101617D 

Farmer John's cows have grown lazy and he would like to get them back in shape! He

has decided that the best way to do this is by setting up haybales in the field and having
the cows jump from the northwest corner of the field to the southeast corner. The field
is an n×n square grid. Note that on a standard map, North is up, South is down, East is
right and West is left.
A cow can only jump straight east or south, never west or north, or even southeast.
They also have a limit k on how many cells they can jump. They can jump over haybales,
empty spaces, or any combination, even if there are no haybales in between, but they
cannot land on a haybale. Bessie wants to still be lazy and is interested in the minimum
number of jumps to reach the southeast corner of the map from the northwest corner.
Input
Each input will consist of a single test case. Note that your program may be run multiple
times on different inputs. Each test case will begin with a line containing two integers n
and k (1 ≤ n,k ≤ 2,000), where n is the size of one side of the square grid, and k is
Bessie’s limit on the number of cells she can jump. Each of the next n lines will contain a
string with exactly n characters. Only the characters ‘#’ (a haybale) and ‘.’ (an empty
space) will appear. The northwest and southeast corners of the field are guaranteed to
be empty.
Output
Output a single integer, which is the minimum number of jumps Bessie needs to reach
the southeast corner from the northwest corner, or -1 if Bessie cannot make it.

Sample Input 

4 2
.###
#...
.#..
#.#.

Sample Output

4


3 1
.#.
.#.

.#.


-1


题意:输入n,k,有一个n*n的矩阵,要从左上角走到右下角,每次只能往右跳或往下跳,小于等于k格,问最少跳几次

思路:对于每一行每一列都建了一个线段树,得到最小值


#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstring>
#define maxn 999999
using namespace std;
char mp[2005][2005];
int dp[2005][2005];
int tree[2][2005][2005*4];
void build(int k, int l, int r, int root)
{
	tree[0][k][root] = tree[1][k][root] = maxn;
	if(l==r) return ;
	int mid = l+r>>1;
	build(k,l,mid,root<<1);
	build(k,mid+1, r, root<<1|1); 
}
void update(int rc, int k, int l, int r, int root, int pos, int num)
{
	if(l==r)
	{
		tree[rc][k][root] = num;
		return;
	}
	int mid = l+r>>1;
	if(pos<=mid) update(rc, k, l, mid, root<<1, pos, num);
	else update(rc, k, mid+1, r, root<<1|1, pos, num);		
	tree[rc][k][root] = min(tree[rc][k][root<<1], tree[rc][k][root<<1|1]);		
}
int query(int rc, int k, int l, int r, int root, int x, int y)
{
	if(x<=l&&y>=r) return tree[rc][k][root];
	int mid = l+r>>1, ans = maxn;
	if(x<=mid) ans = min(ans, query(rc, k, l, mid, root<<1, x, y));
	if(y>mid) ans = min(ans, query(rc, k, mid+1, r, root<<1|1, x, y));
	return ans;	
}

int main()
{
	int n, k;
	scanf("%d%d", &n, &k);
	int i, j, mi;
	for(i = 1; i <= n; i++) build(i, 1, n, 1);
	for(i = 1; i <= n; i++) scanf("%s", mp[i]+1);
	update(0, 1, 1, n, 1, 1, -1);
	update(1, 1, 1, n, 1, 1, -1);
	for(i = 1; i <= n; i++)
	{
		for(j = 1; j <= n; j++)
		{
			dp[i][j] = maxn;
			if(mp[i][j] == '.')
			{
				int x = max(1, j-k), y = max(1, i-k);
				mi = query(0, i, 1, n, 1, x, max(1,j-1));
				dp[i][j] = min(dp[i][j], mi+1);
				mi = query(1, j, 1, n, 1, y, max(1,i-1));
				dp[i][j] = min(dp[i][j], mi+1);
				if(dp[i][j]==maxn) continue;
				update(0, i, 1, n, 1, j, dp[i][j]);
				update(1, j, 1, n, 1, i, dp[i][j]);
			}
		}
	}
	if(dp[n][n]>=maxn) printf("-1\n");
	else printf("%d\n", dp[n][n]);
	return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值