ZOJ FatMouse and Cheese
阿新 • • 發佈:2018-12-02
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);
}
}