2021.04.13找绿洲

2021.04.13找绿洲

题目描述

求方格地图中所有格子到出口(多个)的最小和。描述如下:

一个叫Andy的小朋友在一个正方形的沙漠中迷路了,身边的水也喝完了。Andy知道自己要渴死了,闲得无聊,所以他开始计算一些有趣的问题。

这个沙漠是由一个n*n的网格图构成的,当你站在某一个格子时,你可以走向周围八个格子中的一个。然而,沙漠中的某些格子有毒蛇,你必须避开他们,某些格子有水源,水源就是生命。

现在,Andy希望计算出每个格子到最近的水源的距离。你只需计算出所有距离的和即可。

输入格式

输入的第一行包含三个整数n, m,p,n表示沙漠的边长。m表示毒蛇的个数,p表示绿洲的个数。
接下来m行,输入m个毒蛇的坐标。一行一个
在接下来p行,输入p个绿洲的坐标。一行一个

输出格式

输出一个数,表示沙漠中每个坐标上避开毒蛇,找到绿洲的最短路径长度之和。
若坐标上有毒蛇,或无法从此坐标出发找到绿洲,长度记为-1.
若此坐标上有绿洲,长度记为0.

样例输入

3 1 2
2 1
1 3
3 2

样例输出

6

数据规模和约定

对于60%的数据,0<p<=5。
对于100%的数据,0<n<=3000, 0<p<=3000

思路

使用BFS广搜,可以从绿洲向四周搜索,因为绿洲有多个,所以初始化队列时装入多个状态。

注:以下代码不能AC(60分),望各位朋友解答。

代码

	int MAX_LEN = 3002;
	
	class Node{
		Node(int x, int y, int sco) {
			super();
			this.x = x;
			this.y = y;
			this.sco = sco;
		}
		int x, y;
		int sco;
	}
	
	int n, m, p;
	int[][] dp = new int[MAX_LEN][MAX_LEN];
	boolean[][] vis;
    int[][] dir = {
        {1,0},
        {-1,0},
        {0,1},
        {0,-1},
        {1,1},
        {-1,1},
        {1,-1},
        {-1,-1},
    };
	
	Queue<Node> queue = new LinkedList<>();;
	
	boolean isIn(int i, int j) {
		return i>=1&&i<=n&&j>=1&&j<=n;
	}
	
	void test() throws IOException {
		Reader cin = new Reader();
		n = cin.nextInt();
		m = cin.nextInt();
		p = cin.nextInt();
		
		for(int i = 1; i <= n; i++) for(int j = 1; j <= n; j++) dp[i][j] = Integer.MAX_VALUE;
		
		for(int i = 0; i < m; i++) { //标记毒蛇
			int x = cin.nextInt(), y = cin.nextInt();
			dp[x][y] = -1;
		}
		for(int i = 0; i < p; i++) { //标记绿洲
			int x = cin.nextInt(), y = cin.nextInt();
			dp[x][y] = 0;
			queue.add(new Node(x, y, 0));
		}
		
		vis = new boolean[MAX_LEN][MAX_LEN];
		
		while(!queue.isEmpty()) { // 当队列不为空时
			Node cur = queue.poll();
			for(int k = 0; k < dir.length; k++) {
				int nx = cur.x+dir[k][0];
				int ny = cur.y+dir[k][1];
				int len = cur.sco+1;
				if(isIn(nx, ny) && !vis[nx][ny] && dp[nx][ny]!=-1 && len<dp[nx][ny]) {
					dp[nx][ny] = len;
					Node newNode = new Node(nx, ny, len);
					vis[nx][ny] = true;
					queue.add(newNode);
				}
			}
		}
		
		
		int s = 0;
		for(int i = 1; i <= n; i++) for(int j = 1; j <= n; j++) if(dp[i][j] != -1) {
			if(dp[i][j] != Integer.MAX_VALUE)
				s += dp[i][j];
			else s--;
		}
		System.out.println(s-m);
		
	}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值