ZOJ FatMouse and Cheese
思路:因为题目中提及一直吃到老鼠不能再吃奶酪的情况,所以,对于这种结束的地方不确定的最优化问题,用dp(这里我认为的dp就是递推状态转移,欢迎读者纠正我的说法^ _ ^)是难以求解的,所以用到记忆化搜索的结果就很好。。
博主还是一样的思想,先写递归,再改记忆化
只要写一个递归函数,每次都去寻找老鼠能达到的路线的最大,我用了个flag记录是否有比当前洞更大的奶酪,如果没有就返回值。
了解这个思路后题目就很简单了。。
代码附上:
ps:开头我以为要把检索过的洞的值改为0,以防止路线重叠的情况。。后来发现因为每一次都要找更大的,所以只要从这个洞去寻找下一个洞的时候,就绝对不可能回到这个洞。。
import java.util.Scanner;
public class FatMouseAndCheese {
static int[][] num = new int[105][105];
static int[][] memo = new int[105][105];
static int n;
static int k;
static int memoSearch(int x, int y) {
if(memo[x][y] != -1)
return memo[x][y];
boolean flag = true;
for(int i = 1; i <= k; i++) { //向左寻找路线
if(x-i <= 0)
break;
if(num[x-i][y] <= num[x][y])
continue;
int t = memoSearch(x-i, y);
if(t > memo[x][y]) {
memo[x][y] = t;
flag = false;
}
}
for(int i = 1; i <= k; i++) { //向右寻找路线
if(x+i > n)
break;
if(num[x+i][y] <= num[x][y])
continue;
int t = memoSearch(x+i, y);
if(t > memo[x][y]) {
memo[x][y] = t;
flag = false;
}
}
for(int i = 1; i <= k; i++) { //向上寻找路线
if(y-i <= 0)
break;
if(num[x][y-i] <= num[x][y])
continue;
int t = memoSearch(x, y-i);
if(t > memo[x][y]) {
memo[x][y] = t;
flag = false;
}
}
for(int i = 1; i <= k; i++) { //向下寻找路线
if(y+i > n)
break;
if(num[x][y+i] <= num[x][y])
continue;
int t = memoSearch(x, y+i);
if(t > memo[x][y]) {
memo[x][y] = t;
flag = false;
}
}
if(flag) //如果没找到比当前大的跳出递归
memo[x][y] = 0;
memo[x][y] += num[x][y];
return memo[x][y];
}
static void process(int n) {
for(int i = 1; i <= n; i++)
for(int j = 1; j <= n; j++)
memo[i][j] = -1;
}
/* static void display(int n) { //打印测试的函数
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= n; j++) {
System.out.print(memo[i][j]+" ");
}
System.out.println();
}
}*/
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while(true) {
n = sc.nextInt();
k = sc.nextInt();
if(n == -1 && k == -1)
break;
for(int i = 1; i <= n; i++)
for(int j = 1; j <= n; j++)
num[i][j] = sc.nextInt();
process(n);
System.out.println(memoSearch(1, 1));
}
//display(n);
}
}