POJ 1088 滑雪 && HDU 1078 FatMouse and Cheese (坐标DP两题对比)

POJ 1088 滑雪

HDU 1078 FatMouse and Cheese

两题题意大致相同,做法也相同,差别在于最后输出,到底是直接输出dp[1][1](我使用 1,1 点作为起点),还是在dp数组中选择最大值。我因为没考虑清这个问题,两题分别用了另一题的输出方式。。。。

首先在做滑雪的时候,因为测试样例能够遍历全图,所以我直接在最后输出了dp[1][1],然后提交一直WA,后来翻了翻上课的时候的代码,发现最后是要找最大值,才意识到,因为这题是没有规定起点的,所以每次dfs相当于搜完了跟这个起点连通的,而其他不能到的点是另起炉灶的,所以在最后要找dp数组的最大值。

而老鼠奶酪的刚好相反,规定起点必须是(1,1),结果我想都没想就照着滑雪写了代码。。。WA后才想到这里的区别。。。改完就能A了

这两题算是坐标DP的模板基础题,因此在初学的时候,觉得对比下是有必要的,而且老鼠题还附加了别的条件,也算是不那么基础的基础题吧?

下面两题代码:

POJ 1088

#include<cstdio>  
#include<algorithm>  
using namespace std;  
  
const int dx[] = {0, 0, -1, 1};  
const int dy[] = {1, -1, 0, 0};  
const int N = 1e3;  
int n, m, ans = 0;  
int dp[N][N], a[N][N];  
  
int dfs(int x, int y){  
    if(dp[x][y] > 0) return dp[x][y];  
    dp[x][y] = 1;  
    for(int i = 0; i < 4; i++){  
        int xx = x + dx[i];  
        int yy = y + dy[i];  
        if(xx < 1 || yy < 1 || xx > n || yy > m || a[xx][yy] >= a[x][y]) continue;  
        dp[x][y] = max(dp[x][y], dfs(xx, yy) + 1);   
    }  
    return dp[x][y];  
}  
  
int main(){  
    scanf("%d%d", &n, &m);  
    for(int i = 1; i <= n; i++){  
        for(int j = 1; j <= m; j++) {  
            scanf("%d", &a[i][j]);  
        }   
    }  
    for(int i = 1; i <= n; i++){  
        for(int j = 1; j <= m; j++){  
            if(dp[i][j] == 0) ans = max(ans, dfs(i, j));   
        }  
    }  
    printf("%d\n", ans);  
    return 0;   
}  



HDU 1078

import java.util.Arrays;
import java.util.Scanner;

public class Main{
	static Scanner sc = new Scanner(System.in);
	static int [][] dp = new int[105][105];
	static int [][] map = new int[105][105]; 
	static int dx[] = {0, 0, -1, 1};
	static int dy[] = {1, -1, 0, 0};
	static int n,k,res;
	static int dfs(int x, int y) {
		if(dp[x][y] > 0) return dp[x][y];
		int max = 0;
		for(int i = 0; i < 4; i++){
			for(int j = 1; j <= k; j++) {
				int xx = x + dx[i] * j;
				int yy = y + dy[i] * j;
				if(xx < 1 || yy < 1 || xx > n || yy > n || map[xx][yy] <= map[x][y]) continue;
				max = Math.max(max, dfs(xx, yy)); 
			}
		}
		return dp[x][y] = max + map[x][y];
	}
	public static void main(String[] args) {
		while(sc.hasNext()) {
			n = sc.nextInt(); k = sc.nextInt();
			if(n == -1 && k == -1) break;
			res=0;
			for(int i = 1; i <= n; i++) {
				Arrays.fill(dp[i], 0);
			}
			for(int i = 1; i <= n; i++) {
				for(int j = 1; j <= n; j++) {
					map[i][j] = sc.nextInt();
				}
			}
			for(int i = 1; i <= n; i++) {
				for(int j = 1; j <= n; j++) {
					if(dp[i][j] == 0) 
						res = Math.max(res, dfs(i,j));
				}
			}
			for(int i = 1; i <= n; i++) {
				for(int j = 1; j <= n; j++) {
					System.out.print(dp[i][j]+"  ");
				}
				System.out.println();
			}
			System.out.println(res);
		}
		System.exit(0);
	}
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值