|
|
|
|
package class_2022_03_4_week;
|
|
|
|
|
|
|
|
|
|
// 来自学员问题
|
|
|
|
|
// 大妈一开始手上有x个鸡蛋,她想让手上的鸡蛋数量变成y
|
|
|
|
|
// 操作1 : 从仓库里拿出1个鸡蛋到手上,x变成x+1个
|
|
|
|
|
// 操作2 : 如果手上的鸡蛋数量是3的整数倍,大妈可以直接把三分之二的鸡蛋放回仓库,手里留下三分之一
|
|
|
|
|
// 返回从x到y的最小操作次数
|
|
|
|
|
// 1 <= x,y <= 10^18
|
|
|
|
|
// 练一下,用平凡解做限制
|
|
|
|
|
public class Code08_EggXtoY {
|
|
|
|
|
|
|
|
|
|
// 彻底贪心!
|
|
|
|
|
public static int minTimes1(int x, int y) {
|
|
|
|
|
if (x <= y) {
|
|
|
|
|
return y - x;
|
|
|
|
|
}
|
|
|
|
|
// 0 0
|
|
|
|
|
// 1 2
|
|
|
|
|
// 2 1
|
|
|
|
|
int mod = x % 3;
|
|
|
|
|
// 鸡蛋拿到3的整数倍,需要耗费的行动点数
|
|
|
|
|
int need = mod == 0 ? 0 : (mod == 1 ? 2 : 1);
|
|
|
|
|
return need + 1 + minTimes1((x + 2) / 3, y);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static int minTimes2(int x, int y) {
|
|
|
|
|
if (x <= y) {
|
|
|
|
|
return y - x;
|
|
|
|
|
}
|
|
|
|
|
int limit = minTimes1(x, y);
|
|
|
|
|
int[][] dp = new int[x + limit + 1][limit + 1];
|
|
|
|
|
return process(x, y, 0, limit, dp);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 当前鸡蛋数量cur,目标aim
|
|
|
|
|
// 之前已经用了多少行动点,pre
|
|
|
|
|
// limit : 一定行动点,超过limit,不需要尝试了!
|
|
|
|
|
public static int process(int cur, int aim, int pre, int limit, int[][] dp) {
|
|
|
|
|
if (pre > limit) {
|
|
|
|
|
return Integer.MAX_VALUE;
|
|
|
|
|
}
|
|
|
|
|
if (dp[cur][pre] != 0) {
|
|
|
|
|
return dp[cur][pre];
|
|
|
|
|
}
|
|
|
|
|
int ans = 0;
|
|
|
|
|
if (cur == aim) {
|
|
|
|
|
ans = pre;
|
|
|
|
|
} else {
|
|
|
|
|
int p1 = process(cur + 1, aim, pre + 1, limit, dp);
|
|
|
|
|
int p2 = Integer.MAX_VALUE;
|
|
|
|
|
if (cur % 3 == 0) {
|
|
|
|
|
p2 = process(cur / 3, aim, pre + 1, limit, dp);
|
|
|
|
|
}
|
|
|
|
|
ans = Math.min(p1, p2);
|
|
|
|
|
}
|
|
|
|
|
dp[cur][pre] = ans;
|
|
|
|
|
return ans;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static void main(String[] args) {
|
|
|
|
|
int max = 3000;
|
|
|
|
|
int testTime = 500;
|
|
|
|
|
System.out.println("测试开始");
|
|
|
|
|
for (int i = 0; i < testTime; i++) {
|
|
|
|
|
int x = (int) (Math.random() * max) + 1;
|
|
|
|
|
int y = (int) (Math.random() * max) + 1;
|
|
|
|
|
int ans1 = minTimes1(x, y);
|
|
|
|
|
int ans2 = minTimes2(x, y);
|
|
|
|
|
if (ans1 != ans2) {
|
|
|
|
|
System.out.println("出错了!");
|
|
|
|
|
System.out.println("x = " + x);
|
|
|
|
|
System.out.println("y = " + y);
|
|
|
|
|
System.out.println(ans1);
|
|
|
|
|
System.out.println(ans2);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
System.out.println("测试结束");
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|