zoukankan      html  css  js  c++  java
  • 小象和老鼠 DP

    小象和老鼠 DP

    (N*M)的网格图,格子((i,j))(A_{i,j})个老鼠,问小象从左上角((1,1))走到右下角((N,M))看到的最少老鼠。小象可以看见老鼠,当且仅当老鼠的位置((x2,y2))满足(|x1-x2|+|y1-y2|le1)

    比较有意思的一道DP题,还是比较简单。我们发现如果直接设(f[i][j])跑会导致一些格子重复计算,所以我们可以设(f[i][j][0])表示到位置((i,j))时最少看到的老鼠数量,并且当前状态是从上面转移而来的(f[i][j][1])表示到位置((i,j))时最少看到的老鼠数量,并且当前状态是从左面转移而来的,这样我们便可以获得决策所需要的全部条件,从而避免重复计算。

    转移方程看着图写就好了

    //f[i][j][0]当前状态从上面转移而来
    f[i][j][0]=min(f[i-1][j][1]+mp[i][j+1]+mp[i+1][j], f[i][j][0]);
    f[i][j][0]=min(f[i-1][j][0]+mp[i+1][j]+mp[i][j-1]+mp[i][j+1], f[i][j][0]);
    //f[i][j][0]当前状态从左面转移而来
    f[i][j][1]=min(f[i][j-1][1]+mp[i][j+1]+mp[i-1][j]+mp[i+1][j], f[i][j][1]);
    f[i][j][1]=min(f[i][j-1][0]+mp[i][j+1]+mp[i+1][j], f[i][j][1]);
    

    完整代码:

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #define MAXN 1010
    using namespace std;
    int f[MAXN][MAXN][2],mp[MAXN][MAXN];
    int n,m;
    int calc(int x, int y){
        int res=0;
        if(x+1>=1&&x+1<=n) res+=mp[x+1][y];
        if(x-1>=1&&x-1<=n) res+=mp[x-1][y];
        if(y+1>=1&&y+1<=m) res+=mp[x][y+1];
        if(y-1>=1&&y-1<=m) res+=mp[x][y-1];
        return res+mp[x][y];
    }
    int main(){
        scanf("%d %d", &n, &m);
        for(int i=0;i<=n;++i)
        for(int j=0;j<=m;++j)
            f[i][j][0]=f[i][j][1]=0x3f3f3f3f;
        for(int i=1;i<=n;++i)
        for(int j=1;j<=m;++j)
            scanf("%d", &mp[i][j]);
        f[1][1][0]=f[1][1][1]=calc(1, 1);
        for(int i=1;i<=n;++i)
        for(int j=1;j<=m;++j){
            //f[i][j][0]当前状态从上面转移而来
            f[i][j][0]=min(f[i-1][j][1]+mp[i][j+1]+mp[i+1][j], f[i][j][0]);
            f[i][j][0]=min(f[i-1][j][0]+mp[i+1][j]+mp[i][j-1]+mp[i][j+1], f[i][j][0]);
            //f[i][j][0]当前状态从左面转移而来
            f[i][j][1]=min(f[i][j-1][1]+mp[i][j+1]+mp[i-1][j]+mp[i+1][j], f[i][j][1]);
            f[i][j][1]=min(f[i][j-1][0]+mp[i][j+1]+mp[i+1][j], f[i][j][1]);
        }
        printf("%d", min(f[n][m][0], f[n][m][1]));
        return 0;
    }
    

    这是校内模拟赛做的一道题,一开始以为是道DP签到题导致思路都错了,后面静下心慢慢分析决策才想出正解,可见手推样例重要性。另外一定不要轻敌。

  • 相关阅读:
    [转] Vue + Webpack 组件式开发(练习环境)
    [转] 从零构建 vue2 + vue-router + vuex 开发环境到入门,实现基本的登录退出功能
    [转] Redux入门教程(快速上手)
    [转] 前端数据驱动的价值
    [转] React风格的企业前端技术
    [转] 对Array.prototype.slice.call()方法的理解
    [转] webpack之plugin内部运行机制
    [转] 静态资源的分布对网站加载速度的影响/浏览器对同一域名下并发加载资源数量
    Mysql 版本号、存储引擎、索引查询
    linux 查看CPU、内存、磁盘信息命令
  • 原文地址:https://www.cnblogs.com/santiego/p/11563826.html
Copyright © 2011-2022 走看看