• dp迷宫计数


    1.

    传送门

    我们有一个网格,水平有H行,垂直有W列的正方形。如果Sij是#,则为wall;如果Sij是..,则为road。在正方形(1,1)有一个王后,即国际象棋中的棋子。在一次移动中,它可以向右、向下或斜向右下角移动任意数量的方块,而不需要跳过墙方块。皇后从方格(1,1)移动到方格(H,W)有多少种方式?求模数(1e9+7)。
    在这里,两种旅行方式被认为是不同的,当且仅当存在i使得第i步后女王的位置在这两种方式中不同。

    意思就是说可以向下,向右,或斜向右下角移动任意步,问你从(1,1)到(n,m)有种多少方式

    这个题就是设置三个数组,类似于前缀和

    #include<iostream>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    const int mod=1e9+7;
    const int maxn=2000+100;
    ll dp[maxn][maxn];
    ll xie[maxn][maxn];
    ll up[maxn][maxn];
    ll l[maxn][maxn];
    char a[maxn][maxn];
    int main(){
        int n,m;
        cin>>n>>m;
        for(int i=1;i<=n;i++){
            scanf("%s",a[i]+1); 
        }
        dp[1][1]=1;
        l[1][1]=up[1][1]=xie[1][1]=1;
        for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++){
                if(i==1&&j==1){
                    continue;
                }
                if(a[i][j]=='#'){
                    dp[i][j]=l[i][j]=xie[i][j]=up[i][j]=0;
                }
                else{
                    dp[i][j]=(up[i-1][j]+xie[i-1][j-1]+l[i][j-1])%mod;
                    up[i][j]=(up[i-1][j]+dp[i][j])%mod; 
                    l[i][j]=(l[i][j-1]+dp[i][j])%mod;
                    xie[i][j]=(xie[i-1][j-1]+dp[i][j])%mod;
                } 
            }
        }
        printf("%lld
    ",dp[n][m]);
    } 

    设有 n×m的方格图,每个方格中都有一个整数。现有一只小熊,想从图的左上角走到右下角,每一步只能向上、向下或向右走一格,并且不能重复经过已经走过的方格,也不能走出边界。小熊会取走所有经过的方格中的整数,求它能取到的整数之和的最大值。

    Input

    第一行有两个整数 n,m

    接下来 n 行每行 m 个整数,依次代表每个方格中的整数。

    Output

    一个整数,表示小熊能取到的整数之和的最大值。

    Samples

    Input Copy
    3 4
    1 -1 3 2
    2 -1 4 -1
    -2 2 -3 -1
    Output
    9
    Input Copy
    2 5
    -1 -1 -3 -2 -7
    -2 -1 -4 -1 -2
    Output
    -10

    Hint

    样例1解释:

    按上述走法,取到的数之和为1+2+(-1)+4+3+2+(-1)+(-1)=9,可以证明为最大值。

    注意,上述走法是错误的,因为第2行第2列的方格走过了两次,而根据题意,不能经过已经走过的方格。

    另外,上述走法也是错误的,因为没有走到右下角的终点。

    样例2解释:

    按上述走法,取到的数之和为(-1)+(-1)+(-3)+(-2)+(-1)+(-2)=-10,可以证明为最大值。因此,请注意,取到的数之和的最大值也可能为负数。

    数据范围:

    • 对于 20%20% 的数据,n,m5
    • 对于 40%40% 的数据,n,m50
    • 对于 70%70%的数据,n,m300
    • 对于 100%100%的数据,1n,m1e3。方格中整数的绝对值不超过 104104。

    Source

    2020 CSP J2

    这个肯定是dp

    就是设置三个数组

    ll l[maxn][maxn];
    ll up[maxn][maxn];
    ll down[maxn][maxn];
    分别代表从左边,从上边,从下边更新的最大值
    一定要一列,一列的更新
    要不然那个向从下边的没法更新
    在更新每一类的时候要先正着跟新一边,再倒着更新一边
    转移方程是:
    up[i][j]=max(l[i-1][j],up[i-1][j])+a[i][j];
    l[i][j]=max(l[i][j-1],max(up[i][j-1],down[i][j-1]))+a[i][j];
    down[i][j]=max(l[i+1][j],down[i+1][j])+a[i][j];
     
    #include<iostream>
    #include<algorithm>
    using namespace std;
    const int maxn=2e3+100;
    typedef long long ll;
    const ll INF=-1e18;
    ll a[maxn][maxn];
    ll l[maxn][maxn];
    ll up[maxn][maxn];
    ll down[maxn][maxn];
    int main(){
        int n,m;
        cin>>n>>m;
        for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++){
                cin>>a[i][j];
                l[i][j]=up[i][j]=down[i][j]=INF;
            }
        }
        l[1][1]=up[1][1]=down[1][1]=a[1][1];
        for(int j=1;j<=m;j++){
            for(int i=1;i<=n;i++){
                if(i!=1){
                    up[i][j]=max(l[i-1][j],up[i-1][j])+a[i][j];
                }
                if(j!=1){
                    l[i][j]=max(l[i][j-1],max(up[i][j-1],down[i][j-1]))+a[i][j];
                }
            }
            for(int i=n-1;i>=1;i--){
                down[i][j]=max(l[i+1][j],down[i+1][j])+a[i][j];
            }
        }
        cout<<max(up[n][m],l[n][m])<<endl; 
    }
  • 相关阅读:
    用对象模式实现QTP的远程调用
    Python 常用类库
    User32.dll 函数的相关方法整理
    python ConfigParser – 配置文件解析
    python 中的 __init__()解释
    Access to the database file is not allowed. [ File name = ***\DataBase.sdf
    在遗忘中成长
    在MVC3里如何关闭Form标签
    javascript 中写cookie
    .NET之死和观念的力量【】
  • 原文地址:https://www.cnblogs.com/lipu123/p/13999751.html
Copyright © 2020-2023  润新知