九度 1529:棋盘寻宝(递推DP)

题目描述:

现在有一个8*8的棋盘,上面放着64个价值不等的礼物,每个小的棋盘上面放置一个礼物(礼物的价值大于0小于1000),一个人的初始位置在棋盘的左上角,每次他只能向下或向右移动一步,并拿走对应棋盘上的礼物,结束位置在棋盘的右下角,请设计一个算法使其能够获得最大价值的礼物。

 

思路

Leetcode 原题

dp[i][j] 表示 在第 (i,j) 个格子上能够获得的最大价值的礼物

状态转移方程为

dp[i][j] = max(dp[i-1][j], dp[i][j-1]) + matrix[i][j]

这题不应该再贴上, 不过上次做括号匹配没构造出状态转移方程, 那题与此题思路是类似的

状态方程的求解, 有时递推关系比较明显, 尤其是图, 树, 矩阵什么的, 但有时递推关系就比较隐晦, 比如括号匹配, 铺地板(编程之美)他们类似是因为他们有一个共同点, 即通向当前状态有几种选择. 当是括号时, 可以选择左括号或右括号, 是地板, 可以选择横着放或竖着放 , 当是树或图时, 可以选择是由那个分支

 

代码

#include <iostream>
#include <stdio.h>
using namespace std;

int matrix[10][10];
int dp[10][10];
int dodp(int n) {
    for(int i = 0; i < n; i ++) {
        for(int j = 0; j < n; j++) {
            int left = 0, up = 0;
            dp[i][j] = matrix[i][j];
            if(j-1 >= 0)
                left = dp[i][j-1];
            if(i-1 >= 0)
                up = dp[i-1][j];
            dp[i][j] += max(left, up);
        }
    }

    return dp[n-1][n-1];
}
int main() {
    //freopen("testcase.txt", "r", stdin);
    int n = 8;
    int first = 0;
    while(scanf("%d",&first) != EOF) {
        matrix[0][0] = first;
        for(int i = 1; i < n; i ++)
            scanf("%d", &matrix[0][i]);
        for(int i = 1; i < n; i ++) {
            for(int j = 0; j < n; j ++) {
                scanf("%d", &matrix[i][j]);
            }
        }
        int res = dodp(n);
        cout << res << endl;
    }
    
    return 0;
}

 

 

posted @ 2014-03-04 12:40  SangS  阅读(516)  评论(0编辑  收藏  举报