hdu1078 FatMouse and Cheese 搜索dfs&dp

来源:互联网 发布:淘宝哪家supreme复刻 编辑:程序博客网 时间:2024/05/29 11:23

FatMouse and Cheese

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)



Problem Description
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 11 2 510 11 612 12 7-1 -1
 

Sample Output
37
 

题意
一只老鼠从【0,0】点出发,去吃食物,有以下规定
1、可以上下左右走,每次最多走k个格子,走到后可以吃格子里的食物
2、每次吃的食物要比上一次吃得多才合法。
直到吃到无法再吃了为止

解题思路
这个题其实和poj1088上滑雪那个题很像,只不过比那个稍微再麻烦点。滑雪题链接
两种做法, dfs和dp

dfs的话用记忆化搜索
dp的话是先排序,按食物数量从小到大排序。这样能保证小的都算过了才算大的,也就是算当前点的时候,所用到的比这个点小的点都已经是最优了,这样就能保证子问题最优。
这里要注意不管是dfs还是dp都是要注意 选取往哪个方向走的时候要另开一个变量maxn选出最大的最后再加上当前的a[i][j] 不可直接dp[i][j]=max(dp[i][j],dp[i+k][j]+a[i][j])
因为如果有个点走不过去,那么有比他大的点也不能通过这个点走到,所以要特判一下。

dfs 代码
#include <cstdio>#include <cstring>#include <iostream>#define INF 0x3f3f3f3fusing namespace std;int n,k;int a[110][110];int dp[110][110];int  dfs(int i,int j){    if(dp[i][j]) return dp[i][j];    int left=j-k,right=j+k,up=i-k,down=i+k;    if(left<0) left =0;    if(right>=n) right=n-1;    if(up<0)up =0;    if(down>=n) down=n-1;    int maxn=0;    for(int k=left;k<=right;++k)    {        if(a[i][k]>a[i][j] )          maxn= max(maxn,dfs(i,k));    }    for(int k=up;k<=down;++k)    {        if(a[k][j]>a[i][j])            maxn=max(maxn,dfs(k,j));    }    dp[i][j]=maxn+a[i][j];    return dp[i][j];}int main(){    while(scanf("%d%d",&n,&k) && n!=-1 && k!=-1)    {        memset(dp,0,sizeof(dp));        memset(a,0,sizeof(a));        for(int i=0;i<n;++i)            for(int j=0;j<n;++j)                scanf("%d",&a[i][j]);        printf("%d\n",dfs(0,0));    }    return 0;}


dp 代码
///dp改后已过#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#define INF 0x3f3f3f3fusing namespace std;int n,k;int a[110][110];int dp[110][110];int maxn=0;struct Node{    int x,y,num;}node[10100];int max(int x,int y){    return x>y? x : y;}int cmp(const Node & node1,const Node & node2){    return node1.num<node2.num;}int main(){    while(scanf("%d%d",&n,&k) && n!=-1 && k!=-1)    {        memset(dp,0,sizeof(dp));        memset(a,0,sizeof(a));        for(int i=0;i<n;++i)            for(int j=0;j<n;++j)            {                scanf("%d",&a[i][j]);                node[i*n+j].num=a[i][j];                node[i*n+j].x=i;                node[i*n+j].y=j;            }        sort(node,node+n*n,cmp);        dp[0][0]=a[0][0];        int ans=dp[0][0];        for(int i=0;i<n*n;++i)        {            int x=node[i].x,y=node[i].y;            //如某个数周围都是比他大的则走不到这个数,dp应该为0,但是这个样写下面会改变值            int temp=0;            for(int j=1;j<=k;++j)            {                if(y-j>=0&&a[x][y-j]<a[x][y])                {                    temp = max(temp,dp[x][y-j]);                }                if(y+j<n&&a[x][y+j]<a[x][y])                {                    temp = max(temp,dp[x][y+j]);                }                if(x-j>=0&&a[x-j][y]<a[x][y])                {                    temp = max(temp,dp[x-j][y]);                }                if(x+j<n &&a[x+j][y]<a[x][y])                {                    temp = max(temp,dp[x+j][y]);                }            }            if(temp == 0)//必须写,周围的点都是无法到达的点,那么这个点也无法到达,不能进行下面的步骤            {                continue;            }            else dp[x][y] = temp+a[x][y];            if(dp[x][y]>ans) ans=dp[x][y];        }        printf("%d\n",ans);    }    return 0;}

1 0
原创粉丝点击