【问题描述】
有一种步长基于2的幂次的图bishop,目的是从原点(0, 0)到目的点(finishX, finishY)。如果从(x, y)移动那么所到达的下一个点会有4种可能,分别是:(x + 2^k, y + 2^k)、(x + 2^k, y - 2^k)、(x - 2^k, y + 2^k)、(x - 2^k, y - 2^k),k是非负整数(0或者正整数)。唯一的限制就是所有步骤k取值必须不同。
需要返回一个字符串数组表示从 (0, 0) 到 (finishX, finishY) 所有经历的路径,包括开始点和结束点。每个数组的元素描述所经过点的x,y坐标按照"x, y"的形式表示。如果结果有多种走法,那么返回路径最短和字母顺序在前的走法(顺序为',', '-', '0', '1', ..., '9')。如果不能到达目的那么返回一个空字符串数组。
注:如果走法有A和B两个字符串数组,按照数组index顺序比较两者对应的字符串,假如A较小则结果返回数组A。finishX,finishY取值范围在1至100000000。
定义:
类 BinaryPowerBishop
方法 public String[] getPath(int finishX, int finishY)
测试用例:
1、16 16
Returns: {"0,0", "16,16" }
2、8 24
Returns: {"0,0", "-8,8", "8,24" }
3、11 22
Returns: { }
注:按照走法从点(x1, y1)到点(x2, y2),x1+y1和x2+y2的奇偶性应是相同的,因此对于x, y坐标和为奇数的点是不可到达的。
4、123 321
Returns: {"0,0", "-128,128", "-112,112", "-104,104", "-100,100", "-102,98", "-101,97", "-133,65", "123,321" }
算法思想:
使用递归的方式得到所有可能的组合,由于每个k取值仅能出现一次,因此递归中使用可二次循环的结构,对于没个k分别取得它的四种取值(x + 2^k, y + 2^k)、(x + 2^k, y - 2^k)、(x - 2^k, y + 2^k)、(x - 2^k, y - 2^k)。另外由于递归的次数比较多,为了尽量加快算法速度,程序中的k取值范围定为2^k要刚好大于finishX和finishY的最大值。
有一种步长基于2的幂次的图bishop,目的是从原点(0, 0)到目的点(finishX, finishY)。如果从(x, y)移动那么所到达的下一个点会有4种可能,分别是:(x + 2^k, y + 2^k)、(x + 2^k, y - 2^k)、(x - 2^k, y + 2^k)、(x - 2^k, y - 2^k),k是非负整数(0或者正整数)。唯一的限制就是所有步骤k取值必须不同。
需要返回一个字符串数组表示从 (0, 0) 到 (finishX, finishY) 所有经历的路径,包括开始点和结束点。每个数组的元素描述所经过点的x,y坐标按照"x, y"的形式表示。如果结果有多种走法,那么返回路径最短和字母顺序在前的走法(顺序为',', '-', '0', '1', ..., '9')。如果不能到达目的那么返回一个空字符串数组。
注:如果走法有A和B两个字符串数组,按照数组index顺序比较两者对应的字符串,假如A较小则结果返回数组A。finishX,finishY取值范围在1至100000000。
定义:
类 BinaryPowerBishop
方法 public String[] getPath(int finishX, int finishY)
测试用例:
1、16 16
Returns: {"0,0", "16,16" }
2、8 24
Returns: {"0,0", "-8,8", "8,24" }
3、11 22
Returns: { }
注:按照走法从点(x1, y1)到点(x2, y2),x1+y1和x2+y2的奇偶性应是相同的,因此对于x, y坐标和为奇数的点是不可到达的。
4、123 321
Returns: {"0,0", "-128,128", "-112,112", "-104,104", "-100,100", "-102,98", "-101,97", "-133,65", "123,321" }
- import java.util.ArrayList;
- import java.util.Collections;
- import java.util.List;
- import java.util.Stack;
- public class BinaryPowerBishop {
- private int[] binary = new int[28];
- private int[] flag = new int[binary.length];
- private Stack<String> resStr = new Stack<String>();
- private List<String[]> resList = new ArrayList<String[]>();
- private int finishX;
- private int finishY;
- private int[][] multi = new int[4][2];
- public String[] getPath(int finishX, int finishY) {
- if((finishX+finishY)%2==1)
- return new String[0];
- this.finishX = finishX;
- this.finishY = finishY;
- multi[0][0] = 1; multi[0][1] = 1;
- multi[1][0] = 1; multi[1][1] = -1;
- multi[2][0] = -1; multi[2][1] = 1;
- multi[3][0] = -1; multi[3][1] = -1;
- int max = Math.abs(finishX) > Math.abs(finishY) ? Math.abs(finishX) : Math.abs(finishY);
- int maxIndex = 0;
- for (int i = 0; i < binary.length; i++) {
- binary[i] = 1 << i;
- if (binary[i] >= 2 * max) {
- maxIndex = i;
- break;
- }
- }
- resStr.add("0,0");
- find(0, 0, 0, maxIndex);
- return findMin();
- }
- private void find(int x, int y, int index, int maxIndex) {
- for (int i = index; i < maxIndex; i++) {
- if (flag[i] == 1)
- continue;
- flag[i] = 1;
- for (int k = 0; k < 4; k++) {
- int nextX = binary[i] * multi[k][0];
- int nextY = binary[i] * multi[k][1];
- resStr.push(nextX + "," + nextY);
- nextX = x + nextX;
- nextY = y + nextY;
- if (nextX == this.finishX && nextY == this.finishY) {
- resList.add(resStr.toArray(new String[0]));
- }
- find(nextX, nextY, i, maxIndex);
- if (resStr.size() > 1)
- resStr.pop();
- }
- flag[i] = 0;
- }
- }
- private String[] findMin() {
- if (resList.size() == 0)
- return new String[0];
- List<String> list = new ArrayList<String>();
- int x = 0, y = 0;
- String tmpMax = "", tmp = "", finalStr = this.finishX + ","
- + this.finishY;
- for (String[] str : resList) {
- StringBuffer sb = new StringBuffer();
- sb.append("0,0;");
- int sumx = 0, sumy = 0, maxIndex = 0;
- for (int i = 1; i < str.length; i++) {
- tmpMax = "999999;999999";
- for (int k = 1; k < str.length; k++) {
- if (str[k].equals("a"))
- continue;
- x = sumx + Integer.parseInt(str[k].split(",")[0]);
- y = sumy + Integer.parseInt(str[k].split(",")[1]);
- tmp = x + "," + y;
- if (tmpMax.compareTo(tmp) > 0) {
- tmpMax = tmp;
- maxIndex = k;
- }
- }
- sumx = sumx + Integer.parseInt(str[maxIndex].split(",")[0]);
- sumy = sumy + Integer.parseInt(str[maxIndex].split(",")[1]);
- sb.append(tmpMax + ";");
- str[maxIndex] = "a";
- }
- list.add(sb.toString().substring(0,
- sb.toString().length() - (finalStr + ";").length()));
- }
- Collections.sort(list);
- return (list.get(0) + finalStr).split(";");
- }
- }
算法思想:
使用递归的方式得到所有可能的组合,由于每个k取值仅能出现一次,因此递归中使用可二次循环的结构,对于没个k分别取得它的四种取值(x + 2^k, y + 2^k)、(x + 2^k, y - 2^k)、(x - 2^k, y + 2^k)、(x - 2^k, y - 2^k)。另外由于递归的次数比较多,为了尽量加快算法速度,程序中的k取值范围定为2^k要刚好大于finishX和finishY的最大值。