zoukankan      html  css  js  c++  java
  • 【做题笔记】洛谷P1002过河卒

    虽说是 dp 入门题,但还是有很多细节需要注意


    如果设 (f_{x,y}) 为目标地点为 ((x,y)) 时走的种数,那么答案就是 (f_{n,m})

    在不考虑那只讨厌的马的情况下,对于任意一个坐标 ((i,j)) ,它能走的方案数应该是从上面和左边走来,即 (f_{i-1,j} + f_{i,j-1}) 的值(从上面走来的方案数和从左边走来的和)。

    此时天空一声巨响,一匹马闪亮登场,从题目所给的图中不难发现,这只马影响九个位置的值,使过河卒不能走

    换而言之,马能走的地方,过河卒的统计应该直接跳过。

    那么一个显而易见的思路:设一个数组 (s) ,在开始 dp 前初始化 (s) 数组,将马可能走到的坐标打上标记,然后在 dp 的时候如果当前坐标有这个标记就 (mathtt{continue}) ,否则令 (f_{i,j} = f_{i-1,j} + f_{i,j-1}),初始化 (f_{1,1})(1)

    然而 NOI plus 的出题人会这么良心么???显然非常凉心。如果这样干,一开始就这么干,就会导致初始化 (f) 数组的值被干掉,最后结果都是 (0) 。所以需要判断一下二者的大小,取较大的值,从而避免这个问题,即 (f_{i,j} = max(f_{i,j},f_{i-1,j}+f_{i,j-1}))

    然而 NOI plus 的出题人的心仅仅这么凉么???显然比这要凉得多。由于转移方程设计减法,会导致数组访问一个不存在的负数下标!!!其实解决方法也很简单,也就是把棋盘往下移。

    最后记得开 (mathtt{long long}) !!!

    参考代码

    #include <iostream>
    #include <stdio.h>
    #include <math.h>
    #define ll long long
    
    using namespace std;
    
    ll f[101][101],n,m,mn,mm,s[230][230];
    
    void stop(ll x,ll y)
    {
        s[x][y]=1;
        s[x-1][y-2]=1;
        s[x-2][y-1]=1;
        s[x-2][y+1]=1;
        s[x-1][y+2]=1;
        s[x+1][y-2]=1;
        s[x+2][y-1]=1;
        s[x+1][y+2]=1;
        s[x+2][y+1]=1;
    }
    
    //初始化 s 数组
    
    int main()
    {
        scanf("%lld%lld%lld%lld",&n,&m,&mn,&mm);
    
        n+=2,m+=2,mn+=2,mm+=2; //坐标下移
    
        stop(mn,mm);
    
        f[2][2]=1; //初始化下移
    
        for(int i=2;i<=n;i++) //棋盘下移
        {
            for(int j=2;j<=m;j++) //棋盘下移
            {
                if(s[i][j]) continue;
                f[i][j]=max(f[i][j],f[i-1][j]+f[i][j-1]);
            }
        }
        printf("%lld
    ",f[n][m]);
        return 0;
    }
    
  • 相关阅读:
    yii2.0缓存的使用
    yii2.0框架where条件的使用
    yii2.0自带验证码使用
    spring中MessageSource的配置使用方法1[转]
    DOM、JDOM、DOM4J的区别
    探秘Java虚拟机——内存管理与垃圾回收
    MySQL开发规范和原则大全
    Java Classloader机制解析
    Junit之测试顺序---FixMethodOrder
    MySQL的btree索引和hash索引的区别
  • 原文地址:https://www.cnblogs.com/BlueInRed/p/12322417.html
Copyright © 2011-2022 走看看