初級程式設計--優秀的掃地機器人--java
阿新 • • 發佈:2019-01-10
現在有很多製造商都在賣掃地機器人,它非常有用,能為忙碌的我們分擔家務負擔。不過我們也很難理解為什麼掃地機器人有時候會反覆清掃某一個地方。
假設有一款不會反覆清掃同一個地方的機器人,它只能前後左右移動。舉個例子,如果第1 次向後移動,那麼連續移動3 次時,就會有以下9 種情況( 下圖)。又因為第1 次移動可以是前後左右4 種情況,所以移動3 次時全部路徑有9×4 = 36 種。
※ 最初的位置用0 表示,其後的移動位置用數字表示。
問題:求這個機器人移動12 次時,有多少種移動路徑?
思路:
機器人只能前後左右移動,假設初始位置為{0,0},下一次移動位置只能是{1,0} {-1,0} {0,1} {0,-1}的一種。
附上程式碼
package com.study.algorithm;
import com.alibaba.fastjson.JSONObject;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
/**
* 掃地機器人不重複走法
*/
public class SweepingRobot {
//機器人只會前後左右移動,假定初始位置為{0,0} 移動只能從objects中的一種
private static int[][] objects = {{1, 0}, {-1 , 0}, {0, 1}, {0, -1}};
private static int count = 0;
private static final int N = 12;
public static void main(String[] args) {
List<int[]> steps = new ArrayList<>(N);
//設定初始位置
steps.add(new int[]{0, 0});
count = moveNext(1, steps);
System.out.println(count);
}
/**
* 移動
*
* @param nextStep
* @param steps
* @return
*/
private static int moveNext(int nextStep, List<int[]> steps) {
//走完 N 步,返回 1,增加一次走法
if (steps.size() == N + 1) {
// System.out.println(JSONObject.toJSONString(steps));
show(steps);
return 1;
}
int cnt = 0;
int i;
for (int j = 0; j < objects.length; j++) {
i = nextStep;
//深度優先 走完一次 清空 nextStep 的後幾位
for (int k = steps.size(); k > nextStep; k--) {
steps.remove(k - 1);
}
//下一步移動的座標
int[] next = {steps.get(i - 1)[0] + objects[j][0], steps.get(i - 1)[1] + objects[j][1]};
//如果未移動到以前座標 則繼續走下去
if (!contains(steps, next)) {
steps.add(next);
cnt += moveNext(++i, steps);
}
}
return cnt;
}
/**
* 判斷是否包含
*
* @param steps
* @param next
* @return
*/
private static boolean contains(List<int[]> steps, int[] next) {
boolean result = false;
if (steps == null)
return result;
for (int i = 0; i < steps.size(); i++) {
if (steps.get(i)[0] == next[0] && steps.get(i)[1] == next[1])
return true;
}
return result;
}
/**
* 路徑列印
*
* @param steps
*/
private static void show(List<int[]> steps) {
int min_y = 0;//最小縱座標
int max_y = 0;//最大縱座標
int min_x = 0;//最小橫座標
for (int i = 0; i < steps.size(); i++) {
if (steps.get(i)[1] < min_y)
min_y = steps.get(i)[1];
if (steps.get(i)[1] > max_y)
max_y = steps.get(i)[1];
if (steps.get(i)[0] < min_x)
min_x = steps.get(i)[0];
}
int y = max_y - min_y + 1;//縱座標(路徑多少行)
ArrayList<Node>[] arrayLists = new ArrayList[y];
for (int i = 0; i < steps.size(); i++) {
int y_v = steps.get(i)[1];//縱座標
int x_v = steps.get(i)[0] - min_x + 1;//橫座標
Node node = new Node(i, x_v);
ArrayList<Node> arrayNode = arrayLists[y_v - min_y];
if (arrayNode == null)
arrayNode = new ArrayList<>();
arrayNode.add(node);
arrayNode.sort(new SortByX());
arrayLists[y_v - min_y] = arrayNode;
}
printToConsole(arrayLists);
}
/**
* 列印到console
*
* @param arrayLists
*/
private static void printToConsole(ArrayList<Node>[] arrayLists) {
int length = String.valueOf(N).length() + 1;//取N的長度+1 方便觀察和對齊
String blank = "";
for (int i = 0; i < length; i++) {
blank += " ";
}
for (ArrayList<Node> nodes : arrayLists) {
for (int i = 0; i < nodes.size(); i++) {
int count = i == 0 ? nodes.get(i).getX()
: nodes.get(i).getX() - nodes.get(i - 1).getX();
for (int j = 1; j < count; j++) {
System.out.print(blank);
}
String v = String.valueOf(nodes.get(i).getV());
int v_l = v.length();
if (v_l < length)
for (int j = 0; j < length - v_l; j++) {
v = " " + v;//位數不夠,前補空格
}
System.out.print(v);
}
System.out.println("");
}
String cut_of = "";
for (int i = 0; i <= N; i++) {
cut_of += "***";
}
System.out.println(cut_of);//分割線
}
}
class Node {
private int v;// 值
private int x;// 橫座標
public Node(int v, int x) {
this.v = v;
this.x = x;
}
public Node(int v) {
this.v = v;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getV() {
return v;
}
public void setV(int v) {
this.v = v;
}
}
class SortByX implements Comparator {
@Override
public int compare(Object o1, Object o2) {
return ((Node) o1).getX() - ((Node) o2).getX();
}
}
打印出軌跡的效果如下