HDU - 1078 FatMouse and Cheese【动态规划 + 深度优先搜索】【两种代码】

FatMouse和奶酪

时间限制:2000/1000 MS(Java / Others)内存限制:65536/32768 K(Java /其他)
提交总数:14165接受提交内容:5987

问题描述

FatMouse在一个城市储存了一些奶酪。可以将城市视为维度为n的正方形网格:每个网格位置标记为(p,q),其中0 <= p <n且0 <= q <n。在每个网格位置,Fatmouse在一个洞中隐藏了0到100块奶酪。现在他将享受他最喜欢的食物。

FatMouse从站在(0,0)处开始。他吃掉了他所站立的奶酪,然后水平或垂直地跑到另一个地方。问题是有一只名叫Top Killer的超级猫坐在他的洞附近,所以每次他都可以跑到最多的k个位置进入洞,然后被Top Killer抓住。更糟糕的是 - 在一个地方吃完奶酪后,FatMouse变胖了。因此,为了获得足够的能量进行下一轮比赛,他必须跑到一个比现在的洞更多的奶酪块。

给定n,k和每个网格位置的奶酪块数,计算FatMouse在无法移动之前可以吃的最大奶酪量。

输入

有几个测试用例。每个测试用例包含

一行,包含1到100之间的两个整数:n和k 
n行,每行有n个数字:第一行包含位置(0,0)(0,1)处的干酪块数。 。(0,n-1); 下一行包含位置(1,0),(1,1),...(1,n-1)的奶酪块数,依此类推。
输入以一对-1结束。

产量

对于每行测试用例输出,单个整数给出收集的奶酪块数。 

样本输入

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

样本输出

37

题解:有一个n * n的网格,每个洞里藏有0~100块奶酪;仓鼠从(0,0)开始走,由于一只猫的存在,所以仓鼠每次只能水平或垂直走1~k步;由于吃了奶酪仓鼠会变胖,所以每一次走到的洞里的奶酪都要比上一次多;求仓鼠最多能吃多少块奶酪。

方法:动态规划 + 深度优先搜索

参考别人的代码:

#include <iostream>
#include <cstring>
#include <stack>
using namespace std;

#define INF 0xfffffff
#define maxn 110
int dp[maxn][maxn];//dp[i][j]:从(i,j)开始能获得的最多奶酪 
int cheese[maxn][maxn];//记录每个位置有几块奶酪 
int n,k;//n个洞,每次最多走k步 

int dfs(int a,int b)
{
    if(dp[a][b]) return dp[a][b];
    dp[a][b]=cheese[a][b];
    for(int i=1;i<=k;i++)
    {
        //横坐标正向走i步,且下一个洞奶酪比当前的多 
        if(a+i<n&&cheese[a+i][b]>cheese[a][b])
        {
            dp[a][b]=max(dp[a][b],dfs(a+i,b)+cheese[a][b]);
        }
        //横坐标负向走i步,且下一个洞奶酪比当前的多
        if(a-i>=0&&cheese[a-i][b]>cheese[a][b])
        {
            dp[a][b]=max(dp[a][b],dfs(a-i,b)+cheese[a][b]);
        }
        //纵坐标负向走i步,且下一个洞奶酪比当前的多
        if(b-i>=0&&cheese[a][b-i]>cheese[a][b])
        {
            dp[a][b]=max(dp[a][b],dfs(a,b-i)+cheese[a][b]);
        }
        //纵坐标正向走i步,且下一个洞奶酪比当前的多
        if(b+i<n&&cheese[a][b+i]>cheese[a][b])
        {
            dp[a][b]=max(dp[a][b],dfs(a,b+i)+cheese[a][b]);
        }
    }
    return dp[a][b];
}

int main()
{
    while(cin>>n)
    {
        cin>>k;
        if(n==-1&&k==-1) break;
        memset(dp,0,sizeof(dp));//初始化
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<n;j++)
            {
                cin>>cheese[i][j];
            }
        }
        cout<<dfs(0,0)<<endl;
    }
    return 0;
}

自己简化的代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#define max(a,b) a>b?a:b
using namespace std;
int n,k;
int map[107][107];
int dp[107][107];
int t[4][2]={1,0,-1,0,0,-1,0,1};
int dfs(int x,int y){
	int maxn=0;
	int ans;
	if(dp[x][y]!=-1){
		return dp[x][y];
	}else{
		for(int i=1;i<=k;i++)
			for(int j=0;j<4;j++){
				int xx=x+t[j][0]*i;
				int yy=y+t[j][1]*i;
				if(xx>=0&&yy>=00&&xx<n&&yy<n&&map[xx][yy]>map[x][y]){
					ans=dfs(xx,yy);
					maxn=max(ans,maxn);	
				}	
			}
		return dp[x][y]=maxn+map[x][y];
	}
}
int main(){
	while(scanf("%d%d",&n,&k)!=EOF){
		if(n==-1&&k==-1) break;
		for(int i=0;i<n;i++)
		     for(int j=0;j<n;j++)
			       scanf("%d",&map[i][j]);
	    memset(dp,-1,sizeof(dp)); 
	    printf("%d\n",dfs(0,0));
	}
	return 0;
}

 

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值