• Luogu-P2295 MICE


    题目

    题目链接

     

    测试得分:  100

    主要算法 :  记忆化搜索,动态规划

    题干:

      有后效性DP?

     分析

      伪记忆化搜索:

        考虑起点的特殊情况,预先处理
        Dfs搜出答案,每一次路径看到的老鼠,加上老鼠数目,把看到的老鼠数目所在点的老鼠删除掉
        记得回溯最终得分40分

      代码

    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    #define FORa(i,s,e) for(int i=s;i<=e;i++)
    #define FORs(i,s,e) for(int i=s;i>=e;i--)
    #define gc getchar()//pa==pb&&(pb=(pa=buf)+fread(buf,1,100000,stdin),stdin)?EOF:*pa++
    #define File(name) freopen(name".in","r",stdin);freopen(name".out","w",stdout);
    
    using namespace std;
    char buf[100000],*pa,*pb;
    inline int read();
    
    const int N=1100,M=1100,INF=2147483647;
    int n,m,a[N+1][M+1],s[N+1][M+1],f[N+1][M+1][2];
    int ans=INF,mx[]={0,1,-1,0},my[]={1,0,0,-1};
    
    inline int min(int fa,int fb){return fa<fb?fa:fb;}
    void Init()
    {
        n=read(),m=read();
        FORa(i,1,n) FORa(j,1,m) a[i][j]=read();
    }
    void Dfs(int x,int y,int cnt)
    {
        
        if(s[x][y]<cnt||cnt>=ans) return;
        s[x][y]=cnt;
        if(x==n&&y==m)
        {
            ans=min(cnt,ans);
            return;
        }
        int fx,fy,p[4];
        FORa(i,0,1)
        {
            fx=x+mx[i],fy=y+my[i];
            if(fx<=n&&fy<=m)
            {
                FORa(k,0,3) p[k]=a[fx+mx[k]][fy+my[k]],a[fx+mx[k]][fy+my[k]]=0;
                Dfs(fx,fy,cnt+p[0]+p[1]+p[2]+p[3]);            
                FORa(k,0,3) a[fx+mx[k]][fy+my[k]]=p[k];
            }    
        }
    }
    void Solve_BL()
    {
        memset(s,127,sizeof(s));
        int cnt=a[1][1]+a[1][2]+a[2][1];
        a[1][2]=a[2][1]=a[1][1]=0;
        Dfs(1,1,cnt);
        printf("%d",ans);
    }
    int main()
    {
        Init();
        Solve_BL();
        return 0;
    }
    inline int read()
    {
        register char c(gc);register int f(1),x(0);
        while(c<'0'||c>'9') f=c=='-'?-1:1,c=gc;
        while(c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=gc;
        return x*f;
    }
    /*
    5 5
    86 19 26 18 92 
    25 67 69 28 83 
    54 56 7 5 93 
    63 33 8 66 91 
    68 74 56 92 90 */

      100分DP

        定义:
          a[i][j]表示格子(i,j)中老鼠的数量。
          f[i][j][0]表示当前小象位于格子(i,j)且上一个位置是(i-1,j)所看见的老鼠的最少数量。
          f[i][j][1]表示当前小象位于格子(i,j)且上一个位置是(i,j-1)所看见的老鼠的最少数量
        我们可以得到转移方程:
          f[i][j][0]=min(f[i-1][j][0]+a[i][j-1],f[i-1][j][1])+a[i+1][j]+a[i][j+1]
          f[i][j][1]=min(f[i][j-1][0],f[i][j-1][1]+a[i-1][j])+a[i+1][j]+a[i][j+1]
        最后答案为 min(f[n][m][0],f[n][m][1])。 复杂度:O(N*M)。 

     

    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    #define FORa(i,s,e) for(int i=s;i<=e;i++)
    #define FORs(i,s,e) for(int i=s;i>=e;i--)
    #define gc getchar()//pa==pb&&(pb=(pa=buf)+fread(buf,1,100000,stdin),stdin)?EOF:*pa++
    #define File(name) freopen(name".in","r",stdin);freopen(name".out","w",stdout);
    
    using namespace std;
    char buf[100000],*pa,*pb;
    inline int read();
    
    const int N=1100,M=1100;
    int n,m,f[N+1][M+1][2],a[N+1][M+1];
    
    inline int min(int fa,int fb){return fa<fb?fa:fb;}
    void Solve_Dp()
    {
        memset(f,63,sizeof(f));
        n=read(),m=read();
        FORa(i,1,n) FORa(j,1,m) a[i][j]=read(); 
        f[1][1][0]=f[1][1][1]=a[1][1]+a[1][2]+a[2][1];
        FORa(i,1,n)
            FORa(j,1,m)
                if(i*j!=1)
                {
                    f[i][j][0]=min(f[i][j-1][0]+a[i-1][j],f[i][j-1][1])+a[i+1][j]+a[i][j+1];
                    f[i][j][1]=min(f[i-1][j][1]+a[i][j-1],f[i-1][j][0])+a[i+1][j]+a[i][j+1];
                }
        printf("%d
    ",min(f[n][m][0],f[n][m][1]));
    }
    int main()
    {
        File("lemouse");
        Solve_Dp();
        return 0;
    }
    inline int read()
    {
        register char c(gc);register int f(1),x(0);
        while(c<'0'||c>'9') f=c=='-'?-1:1,c=gc;
        while(c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=gc;
        return x*f;
    }
    /*
    5 5
    86 19 26 18 92 
    25 67 69 28 83 
    54 56 7 5 93 
    63 33 8 66 91 
    68 74 56 92 90 */

    总结:

       确定动规模型

  • 相关阅读:
    j函数 判断以 什么开头
    vue 自定义封装组件 使用 model 选项
    学习旧岛小程序 (3)组件的样式
    JavaScript事件处理程序的3种方式
    常用的JS页面跳转代码调用大全
    JS基础知识:Javascript事件触发列表
    详解JavaScript中的事件处理
    常用的JavaScript字符串处理函数及用法
    如何利用CSS代码使图片和文字在同一行显示且对齐
    利用DIV+CSS制作网页过程中常用的基本概念及标签使用细节
  • 原文地址:https://www.cnblogs.com/SeanOcean/p/11366054.html
Copyright © 2020-2023  润新知