【搜索】B055_LQ_梅花桩(bfs / 贪心)

一、Problem

小明每天都要练功,练功中的重要一项是梅花桩。 小明练功的梅花桩排列成 n 行 m 列,相邻两行的距离为 1,相邻两列的距离也为 1。

小明站在第 1 行第 1 列上,他要走到第 n 行第 m 列上。小明已经练了一段时间,他现在可以一步移动不超过 d 的距离(直线距离)。

小明想知道,在不掉下梅花桩的情况下,自己最少要多少步可以移动到目标。

输入

输入的第一行包含两个整数 n,m,分别表示梅花桩的行数和列数。

第二行包含一个实数 dd(最多包含一位小数),表示小明一步可以移动的距离。

输出

输出一个整数,表示小明最少多少步可以到达目标。

输入
3 4
1.5
输出
3

二、Solution

方法一:bfs

0 分写法:D - dd 这种写法是有问题的,因为我想探索我一步最多能走几个梅花桩,所以

import java.util.*;
import java.math.*;
import java.io.*;
public class Main{
	static class Solution {
		int n, m;
		double d, exp = 1e-6;
		final int[][] dir = {{1,0}, {0,1}, {1, 1}};
		double dist(int x, int y, int x1, int y1) {
		    int xx = x1 - x, yy = y1 - y;
		    return Math.sqrt(xx*xx + yy*yy);
		}
		int bfs() {
			Queue<Pos> q = new ArrayDeque<>();
			q.add(new Pos(0, 0, 0));
			boolean[][] vis = new boolean[n][m];
			
			while (!q.isEmpty()) {
				Pos t = q.poll();
				if (t.x == n-1 && t.y == m-1)
					return t.s;
				for (int k = 0; k < 3; k++) {
				    double tt = d, dd = 0;
				    int tx = t.x, ty = t.y;
				    while (tt > dd) {
				        tx += dir[k][0];
				        ty += dir[k][1];
    					if (tx >= n || ty >= m || vis[tx][ty])
    						continue;
    				    dd = dist(t.x, t.y, tx, ty);
    					tt -= dd;
    					q.add(new Pos(tx, ty, t.s+1));
			    	    vis[tx][ty] = true;
				    }
				}
			}
			return 0;
		}
		void init() {
			Scanner sc = new Scanner(new BufferedInputStream(System.in));
			n = sc.nextInt(); m = sc.nextInt();
			d = sc.nextDouble();
			System.out.println(bfs());
		}
		class Pos {
			int x, y, s;
			public Pos(int x, int y, int s) {
				this.x = x; this.y = y; this.s = s;
			}
		}
	}
    public static void main(String[] args) throws IOException {  
        Solution s = new Solution();
		s.init();
    }
}

修改后的逻辑:得 9/30 分

import java.util.*;
import java.math.*;
import java.io.*;
public class Main{
	static class Solution {
		int n, m, D;
		double d, exp = 1e-6;
		final int[][] dir = {{1,0}, {0,1}, {1, 1}};
		double dist(int x, int y, int x1, int y1) {
		    int xx = x1 - x, yy = y1 - y;
		    return Math.sqrt(xx*xx + yy*yy);
		}
		int bfs() {
			Queue<Pos> q = new ArrayDeque<>();
			q.add(new Pos(1, 1, 0));
			boolean[][] vis = new boolean[n+1][m+1];
			
			while (!q.isEmpty()) {
				Pos t = q.poll();
				if (t.x == n && t.y == m)
					return t.s;
				for (int k = 0; k < 3; k++) {
				    int tx = t.x, ty = t.y;
				    while (tx <= Math.min(n, t.x+D) && ty <= Math.min(m, t.y+D)) {
				        tx += dir[k][0];
				        ty += dir[k][1];
    					if (tx > n || ty > m || vis[tx][ty])
    						continue;
    				    double dd = dist(t.x, t.y, tx, ty);
    				    if (d > dd) {
    				        q.add(new Pos(tx, ty, t.s+1));
			    	        vis[tx][ty] = true;
    				    }
				    }
				}
			}
			return 0;
		}
		void init() {
			Scanner sc = new Scanner(new BufferedInputStream(System.in));
			n = sc.nextInt(); m = sc.nextInt();
			d = sc.nextDouble();
			D = (int) d;
			System.out.println(bfs());
		}
		class Pos {
			int x, y, s;
			public Pos(int x, int y, int s) {
				this.x = x; this.y = y; this.s = s;
			}
		}
	}
    public static void main(String[] args) throws IOException {  
        Solution s = new Solution();
		s.init();
    }
}

怒改 3 个小时

import java.util.*;
import java.math.*;
import java.io.*;
public class Main{
	static class Solution {
		int n, m, D;
		double d, exp = 1e-6;
		double dist(int x, int y, int x1, int y1) {
		    int xx = x1 - x, yy = y1 - y;
		    return Math.sqrt(xx*xx + yy*yy);
		}
		int bfs() {
			Queue<Pos> q = new ArrayDeque<>();
			q.add(new Pos(1, 1, 0));
			boolean[][] vis = new boolean[n+1][m+1];
			vis[1][1] = true;
			while (!q.isEmpty()) {
				Pos t = q.poll();
				if (t.x == n && t.y == m)
					return t.s;
				for (int i = t.x; i <= Math.min(n, t.x+D); i++)
			    for (int j = t.y; j <= Math.min(m, t.y+D); j++) {
			        if (vis[i][j])
			            continue;
		            double dd = dist(t.x, t.y, i, j);
		            if (dd < d) {
		                q.add(new Pos(i, j, t.s+1));
		                vis[i][j] = true;
		            }
			    }
			}
			return 0;
		}
		void init() {
			Scanner sc = new Scanner(new BufferedInputStream(System.in));
			n = sc.nextInt(); m = sc.nextInt();
			d = sc.nextDouble();
			D = (int) d;
			System.out.println(bfs());
		}
		class Pos {
			int x, y, s;
			public Pos(int x, int y, int s) {
				this.x = x; this.y = y; this.s = s;
			}
		}
	}
    public static void main(String[] args) throws IOException {  
        Solution s = new Solution();
		s.init();
    }
}

勾股定理可以不转化为实际距离,可以直接用 a2+b2=c2a^2 + b^2 = c^2 算,但有溢出风险。

但还是超时了… 18/30 吧…

复杂度分析

  • 时间复杂度:O(...)O(...)
  • 空间复杂度:O(...)O(...)

方法二:贪心

为什么要想得那么复杂呢?直接走对角线不好吗?

import java.util.*;
import java.math.*;
import java.io.*;
public class Main{
	static class Solution {
		void init() {
			Scanner sc = new Scanner(new BufferedInputStream(System.in));
			int n = sc.nextInt()-1, m = sc.nextInt()-1;
			double d = sc.nextDouble();
			double dd = Math.sqrt(n*n + m*m);
			System.out.println((int) Math.ceil(dd/d));
		}
	}
    public static void main(String[] args) throws IOException {  
        Solution s = new Solution();
		s.init();
    }
}

复杂度分析

  • 时间复杂度:O(1)O(1)
  • 空间复杂度:O(1)O(1)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章