You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

145 lines
3.9 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

package class51;
import java.util.Arrays;
import java.util.HashSet;
// leetcode题目 : https://leetcode-cn.com/problems/programmable-robot/
public class LCP_0003_Robot {
public static boolean robot1(String command, int[][] obstacles, int x, int y) {
int X = 0;
int Y = 0;
HashSet<Integer> set = new HashSet<>();
set.add(0);
for (char c : command.toCharArray()) {
X += c == 'R' ? 1 : 0;
Y += c == 'U' ? 1 : 0;
set.add((X << 10) | Y);
}
// 不考虑任何额外的点,机器人能不能到达,(xy)
if (!meet1(x, y, X, Y, set)) {
return false;
}
for (int[] ob : obstacles) { // ob[0] ob[1]
if (ob[0] <= x && ob[1] <= y && meet1(ob[0], ob[1], X, Y, set)) {
return false;
}
}
return true;
}
// 一轮以内X往右一共有几个单位
// Y, 往上一共有几个单位
// set, 一轮以内的所有可能性
// (x,y)要去的点
// 机器人从(0,0)位置,能不能走到(x,y)
public static boolean meet1(int x, int y, int X, int Y, HashSet<Integer> set) {
if (X == 0) { // Y != 0 往上肯定走了!
return x == 0;
}
if (Y == 0) {
return y == 0;
}
// 至少几轮?
int atLeast = Math.min(x / X, y / Y);
// 经历过最少轮数后x剩多少
int rx = x - atLeast * X;
// 经历过最少轮数后y剩多少
int ry = y - atLeast * Y;
return set.contains((rx << 10) | ry);
}
// 此处为一轮以内x和y最大能移动的步数对应的2的几次方
// 比如本题x和y最大能移动1000步就对应2的10次方
// 如果换一个数据量x和y最大能移动5000步就对应2的13次方
// 只需要根据数据量修改这一个变量,剩下的代码不需要调整
public static final int bit = 10;
// 如果x和y最大能移动的步数对应2的bit次方
// 那么一个坐标(x,y),所有的可能性就是:(2 ^ bit) ^ 2 = 2 ^ (bit * 2)
// 也就是,(1 << (bit << 1))个状态记为bits
public static int bits = (1 << (bit << 1));
// 为了表示下bits个状态需要几个整数
// 32位只需要一个整数所以bits个状态需要bits / 32 个整数
// 即整型长度需要 : bits >> 5
public static int[] set = new int[bits >> 5];
public static boolean robot2(String command, int[][] obstacles, int x, int y) {
Arrays.fill(set, 0);
set[0] = 1;
int X = 0;
int Y = 0;
for (char c : command.toCharArray()) {
X += c == 'R' ? 1 : 0;
Y += c == 'U' ? 1 : 0;
add((X << 10) | Y);
}
if (!meet2(x, y, X, Y)) {
return false;
}
for (int[] ob : obstacles) {
if (ob[0] <= x && ob[1] <= y && meet2(ob[0], ob[1], X, Y)) {
return false;
}
}
return true;
}
public static boolean meet2(int x, int y, int X, int Y) {
if (X == 0) {
return x == 0;
}
if (Y == 0) {
return y == 0;
}
int atLeast = Math.min(x / X, y / Y);
int rx = x - atLeast * X;
int ry = y - atLeast * Y;
return contains((rx << 10) | ry);
}
public static void add(int status) {
set[status >> 5] |= 1 << (status & 31);
}
public static boolean contains(int status) {
return (status < bits) && (set[status >> 5] & (1 << (status & 31))) != 0;
}
// int num -> 32位的状态
// 请打印这32位状态
public static void printBinary(int num) {
for (int i = 31; i >= 0; i--) {
System.out.print((num & (1 << i)) != 0 ? "1" : "0");
}
System.out.println();
}
public static void main(String[] args) {
int x = 7;
printBinary(x);
int y = 4;
printBinary(y);
// x_y 组合!
int c = (x << 10) | y;
printBinary(c);
System.out.println(c);
// 0 ~ 1048575 任何一个数bit来表示的
// int[] set = new int[32768];
// set[0] = int 32 位 0~31这些数出现过没出现过
// set[1] = int 32 位 32~63这些数出现过没出现过
// 0 ~ 1048575
// int[] set = new int[32768];
// int num = 738473; // 32 bit int
//// set[ 734873 / 32 ] // 734873 % 32
// boolean exist = (set[num / 32] & (1 << (num % 32))) != 0;
}
}