【搜索】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)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章