Monkey and Banana
http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=1093
ps:该题个人认为我的初始方法比较暴力,可能不是暴力解,,这是看了别人一点思路直接自己写的,,没看具体代码,可能部分需要改,,持续更新
一开始写了一种终极无敌暴力的递归做法。。个人认为挺好理解的hhh
因为这题砖头是三维的,而且可以随意转动,并且每个砖头可以选取无数多个。。所以我直接把1个砖头转化为6个砖头,这样子随意转动问题就解决了。。。
然后我就像搜索一样做,写一个recursion(int x, int y, int i)的函数,,该函数表示堆叠过程中最顶一块砖头的长和宽分别为 x 和 y ,i 是砖头的编号。
(这里注意!!如果只用递归的话,第三个参数i也是可以不用的)
之后的操作就是每次递归去找适合的砖头放在它上面并继续进入递归,,用一个变量flag表示上面还能不能放砖头,如果不能就返回0;
结果没错!肯定是非常暴力的不能AC的,但是!!再把递归转记忆化搜索就好了这里不解释记忆化搜索
代码如下:
import java.util.Scanner;
public class MonkeyAndBanana {
static int[] memo = new int[10000];
static int[][] box = new int[10000][3];
static int n;
static int recursion(int x, int y, int i) {
if(memo[i] != -1)
return memo[i];
boolean flag = true; //flag变量用来记录上方是否还能放砖头
for(int j = 0; j < 6*n; j++) {
if(box[j][0] < x && box[j][1] < y) {
flag = false;
int now = recursion(box[j][0], box[j][1], j)+box[j][2];
memo[i] = now > memo[i]? now : memo[i];
}
}
if(flag) //不能就跳出
return 0;
return memo[i];
}
static void process(int i, int x, int y, int z) { //预处理,把输入的1个砖块转化为6个方向的砖块
box[i][0] = x;
box[i][1] = y;
box[i][2] = z;
}
static void process1(int n) { //预处理,把记忆数组初始化为-1
for(int i = 0; i < 6*n; i++) {
memo[i] = -1;
}
}
/* static void display() { //测试函数
for(int i = 0; i < 6*n; i++) {
for(int j = 0; j < 3; j++) {
System.out.print(box[i][j]+" ");
}
System.out.println();
}
}*/
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int count = 1;
while(sc.hasNext()) {
n = sc.nextInt();
if(n == 0)
break;
for(int i = 0; i < 6*n;) {
int x = sc.nextInt();
int y = sc.nextInt();
int z = sc.nextInt();
process(i++, x, y, z);
process(i++, x, z, y);
process(i++, y, x, z);
process(i++, y, z, x);
process(i++, z, x, y);
process(i++, z, y, x);
}
int ans = 0;
process1(n);
for(int i = 0; i < 6*n; i++) {
int now;
if(memo[i] != -1)
now = memo[i];
else
now = recursion(box[i][0], box[i][1], i)+box[i][2];
ans = ans > now? ans:now;
}
System.out.println("Case "+count+": maximum height = "+ans);
count++;
//display();
}
}
}
理解了别人的最优解会更新