• 矩形内的递推dp


    链接:https://www.nowcoder.com/acm/contest/130/B
    来源:牛客网

    黑妹和黑弟又聚在一起玩游戏了,这次他们选择在一个n*m的棋盘上玩游戏,棋盘上的每个方格都有一个非负的分数,
    游戏从左上角开始右下角结束,双方交替的选择一个方格并获得方格上相应的分数,一方选择的方格必须在上一步另一方选择的方格
    的右边或者下面,黑妹先开始。现在黑妹想知道,如果双方都采取最优策略(最优策略是指双方都希望最终自己的总分数减去对方的总分数最大),她的总分数减去黑弟的总分数会是多少?

    输入描述:

    第一行一个整数T表示数据的组数。(1 ≤ T ≤ 20)
    对于每组数据:
    第一行两个整数n,m表示棋盘的规格。(1 ≤ n, m ≤ 500)
    接下来n行每行m个整数aij表示方格对应的分数。(

    )

    输出描述:

    对于每组数据输出一行表示答案。
    示例1

    输入

    复制
    1 
    2 2 
    1 3 
    4 5

    输出

    复制
    2


    思路分析 : 两个方向,第一个是考虑记忆化的搜索,对于一个位置很容易判断出来,他是先走的人走的还是后走的人走的,先走的人下一个位置一定是选小的,后走的人下一步一定是选大的。
    代码示例:
    const int inf = 0x3f3f3f3f;
     
    int n, m;
    int mp[505][505];
    int dp[505][505];
     
    int dfs(int x, int y){
        if (dp[x][y] != inf) return dp[x][y];
         
        if ((x+y)%2 == 0){
            if (x == n && y == m) return dp[x][y] = mp[x][y];
             
            int res = inf;
            if (x < n) res = min(res, dfs(x+1, y));
            if (y < m) res = min(res, dfs(x, y+1));
             
            return dp[x][y] = mp[x][y]+res;
        }
        else {
            if (x == n && y == m) return dp[x][y] = -mp[x][y];
             
            int res = -inf;
            if (x < n) res = max(res, dfs(x+1, y));
            if (y < m) res = max(res, dfs(x, y+1));
             
            return dp[x][y] = res-mp[x][y];
        }
    }
     
    int main() {
        //freopen("in.txt", "r", stdin);
        //freopen("out.txt", "w", stdout);
        int t;
         
        cin >> t;
        while(t--){
            scanf("%d%d", &n, &m);
            for(int i = 1; i <= n; i++){
                for(int j = 1; j <= m; j++){
                    dp[i][j] = inf;
                    scanf("%d", &mp[i][j]);           
                }
            }
            //memset(dp, inf, sizeof(dp));
            int ans = dfs(1, 1);
            printf("%d
    ", ans);
            //printf("+++ %d %d %d %d 
    ", dp[1][1], dp[1][2], dp[2][1], dp[2][2]);   
        }
        return 0;
    }
    

     思路二 :考虑dp

    dp[i][j]表示以 i, j 为起点到达终点的答案的最大值,但是要注意的是从终点往回去推

    代码示例:

    const int inf = 0x3f3f3f3f;
    
    int n, m;
    int mp[505][505];
    int dp[505][505];
    
    int main() {
        //freopen("in.txt", "r", stdin);
        //freopen("out.txt", "w", stdout);
        int t;
        
        cin >>t;
        while(t--){
            scanf("%d%d", &n, &m);
            for(int i = 1; i <= n; i++){
                for(int j = 1; j <= m; j++){
                    scanf("%d", &mp[i][j]);            
                }
            }
                  
            //memset(dp, 0, sizeof(dp));  
            for(int i = n; i >= 1; i--){
                for(int j = m; j >= 1; j--){
                    if (i == n && j == m) dp[i][j] = mp[i][j];
                    else if (i == n) dp[i][j] = mp[i][j]-dp[i][j+1];
                    else if (j == m) dp[i][j] = mp[i][j]-dp[i+1][j];
                    else {
                        dp[i][j] = mp[i][j]-max(dp[i+1][j], dp[i][j+1]);
                    }
                }
            }
            printf("%d
    ", dp[1][1]);
            
        }
        return 0;
    }
    
    东北日出西边雨 道是无情却有情
  • 相关阅读:
    SDUT 2128 树结构练习——排序二叉树的中序遍历
    SDUT 2137 数据结构实验之求二叉树后序遍历和层次遍历
    SDUT 3341 数据结构实验之二叉树二:遍历二叉树
    总结:串和数组的学习
    SDUT 3347 数据结构实验之数组三:快速转置
    SDUT 3348 数据结构实验之数组二:稀疏矩阵
    SDUT 1500 Message Flood
    SDUT 2463 学密码学一定得学程序
    SDUT 2125 数据结构实验之串二:字符串匹配
    mybatis学习(七)(choose的学习)
  • 原文地址:https://www.cnblogs.com/ccut-ry/p/9251923.html
Copyright © 2020-2023  润新知