1. 程式人生 > >HDU 1078 dfs+dp之記憶化搜尋的體現

HDU 1078 dfs+dp之記憶化搜尋的體現

FatMouse has stored some cheese in a city. The city can be considered as a square grid of dimension n: each grid location is labelled (p,q) where 0 <= p < n and 0 <= q < n. At each grid location Fatmouse has hid between 0 and 100 blocks of cheese in a hole. Now he's going to enjoy his favorite food.  FatMouse begins by standing at location (0,0). He eats up the cheese where he stands and then runs either horizontally or vertically to another location. The problem is that there is a super Cat named Top Killer sitting near his hole, so each time he can run at most k locations to get into the hole before being caught by Top Killer. What is worse -- after eating up the cheese at one location, FatMouse gets fatter. So in order to gain enough energy for his next run, he has to run to a location which have more blocks of cheese than those that were at the current hole.  Given n, k, and the number of blocks of cheese at each grid location, compute the maximum amount of cheese FatMouse can eat before being unable to move. 

Input

There are several test cases. Each test case consists of  a line containing two integers between 1 and 100: n and k  n lines, each with n numbers: the first line contains the number of blocks of cheese at locations (0,0) (0,1) ... (0,n-1); the next line contains the number of blocks of cheese at locations (1,0), (1,1), ... (1,n-1), and so on.  The input ends with a pair of -1's. 

Output

For each test case output in a line the single integer giving the number of blocks of cheese collected. 

Sample Input

3 1
1 2 5
10 11 6
12 12 7
-1 -1

Sample Output

37

先說一下題意:有一個n*n的地圖,這個地圖中的每一個點都有權值,要求從(0,0)點開始找一條路徑,這條路徑的權值要求是遞增的,每次都可以在水平或者垂直方向移動不超過k個位置,然後輸出最大的路徑權值

思路:剛開始以為是最長上升子序列的變形,但是仔細想想二維還帶方向,怎麼跟dfs差不多,但就是沒辦法實現,看了別人的題解之後才知道是dfs與dp的結合;

dfs肯定就是搜尋路徑的,dp是幹什麼的?-----記憶化搜尋;直接暴力搜尋這樣一條條路徑肯定會爆,但是仔細想一想,走過的路徑上的權值是可以進行儲存的,既然能夠儲存那就可以進行優化,將這些值用DP陣列存下來,那麼這樣就可以記憶化搜尋了

具體情況看程式碼就好:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include <algorithm>
using namespace std;
const int INF=0x3f3f3f3f;
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define init(a,b) memset(a,b,sizeof a)
int dp[200][200];
int a[200][200];
int n,k;
int xx[]={0,-1,0,1};//路徑dfs用的,這裡就不用多說了
int yy[]={1,0,-1,0};
bool check(int i,int j)//判斷是否越界
{
    if(i<0||i>=n||j<0||j>=n)
        return false;
    return true;
}
int dfs(int x,int y)
{
    int ans=0;
    if(!dp[x][y])//搜尋過程發現走過了,那就不需要再繼續搜尋了
    {
        rep(l,0,3)
        {
            rep(p,1,k)//這層for迴圈是為了再水平還是垂直方向的移動單位
            {
            int i=x+xx[l]*p;
            int j=y+yy[l]*p;
                if(check(i,j)&&a[i][j]>a[x][y])
                {
                    int temp=dfs(i,j);
                    ans=max(temp,ans);
                }
            }
        }
        dp[x][y]=ans+a[x][y];
    }
    return dp[x][y];//不是遞迴結束,而是返回上一步;
}
int main()
{
    while(scanf("%d%d",&n,&k)!=EOF)
    {
        if(n==-1||k==-1) break;
        rep(i,0,n-1)
        rep(j,0,n-1)
        scanf("%d",&a[i][j]);
        init(dp,0);
        printf("%d\n",dfs(0,0));
    }
    return 0;
}