Topcoder_3_159

【问题描述】
    有一种步长基于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" }
  1. import java.util.ArrayList;
  2. import java.util.Collections;
  3. import java.util.List;
  4. import java.util.Stack;
  5. public class BinaryPowerBishop {
  6.     private int[] binary = new int[28];
  7.     private int[] flag = new int[binary.length];
  8.     private Stack<String> resStr = new Stack<String>();
  9.     private List<String[]> resList = new ArrayList<String[]>();
  10.     private int finishX;
  11.     private int finishY;
  12.     private int[][] multi = new int[4][2];
  13.     public String[] getPath(int finishX, int finishY) {
  14.         if((finishX+finishY)%2==1)
  15.             return new String[0];
  16.         
  17.         this.finishX = finishX;
  18.         this.finishY = finishY;
  19.         
  20.         multi[0][0] = 1;        multi[0][1] = 1;
  21.         multi[1][0] = 1;        multi[1][1] = -1;
  22.         multi[2][0] = -1;       multi[2][1] = 1;
  23.         multi[3][0] = -1;       multi[3][1] = -1;
  24.         int max = Math.abs(finishX) > Math.abs(finishY) ? Math.abs(finishX) : Math.abs(finishY);
  25.         int maxIndex = 0;
  26.         for (int i = 0; i < binary.length; i++) {
  27.             binary[i] = 1 << i;
  28.             if (binary[i] >= 2 * max) {
  29.                 maxIndex = i;
  30.                 break;
  31.             }
  32.         }
  33.         resStr.add("0,0");
  34.         find(000, maxIndex);
  35.         return findMin();
  36.     }
  37.     
  38.     private void find(int x, int y, int index, int maxIndex) {
  39.         for (int i = index; i < maxIndex; i++) {
  40.             if (flag[i] == 1)
  41.                 continue;
  42.             flag[i] = 1;
  43.             for (int k = 0; k < 4; k++) {
  44.                 int nextX = binary[i] * multi[k][0];
  45.                 int nextY = binary[i] * multi[k][1];
  46.                 resStr.push(nextX + "," + nextY);
  47.                 nextX = x + nextX;
  48.                 nextY = y + nextY;
  49.                 if (nextX == this.finishX && nextY == this.finishY) {
  50.                     resList.add(resStr.toArray(new String[0]));
  51.                 }
  52.                 find(nextX, nextY, i, maxIndex);
  53.                 if (resStr.size() > 1)
  54.                     resStr.pop();
  55.             }
  56.             flag[i] = 0;
  57.         }
  58.     }
  59.     private String[] findMin() {
  60.         if (resList.size() == 0)
  61.             return new String[0];
  62.         List<String> list = new ArrayList<String>();
  63.         int x = 0, y = 0;
  64.         String tmpMax = "", tmp = "", finalStr = this.finishX + ","
  65.                 + this.finishY;
  66.         for (String[] str : resList) {
  67.             StringBuffer sb = new StringBuffer();
  68.             sb.append("0,0;");
  69.             int sumx = 0, sumy = 0, maxIndex = 0;
  70.             for (int i = 1; i < str.length; i++) {
  71.                 tmpMax = "999999;999999";
  72.                 for (int k = 1; k < str.length; k++) {
  73.                     if (str[k].equals("a"))
  74.                         continue;
  75.                     x = sumx + Integer.parseInt(str[k].split(",")[0]);
  76.                     y = sumy + Integer.parseInt(str[k].split(",")[1]);
  77.                     tmp = x + "," + y;
  78.                     if (tmpMax.compareTo(tmp) > 0) {
  79.                         tmpMax = tmp;
  80.                         maxIndex = k;
  81.                     }
  82.                 }
  83.                 sumx = sumx + Integer.parseInt(str[maxIndex].split(",")[0]);
  84.                 sumy = sumy + Integer.parseInt(str[maxIndex].split(",")[1]);
  85.                 sb.append(tmpMax + ";");
  86.                 str[maxIndex] = "a";
  87.             }
  88.             list.add(sb.toString().substring(0,
  89.                     sb.toString().length() - (finalStr + ";").length()));
  90.         }
  91.         Collections.sort(list);
  92.         return (list.get(0) + finalStr).split(";");
  93.     }
  94. }


  算法思想:
    使用递归的方式得到所有可能的组合,由于每个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的最大值。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值