迷宫

链接:https://ac.nowcoder.com/acm/contest/7412/I
来源:牛客网

题目描述

有一个n×m的网格地图,每个点有个值aij,现在牛牛要从(1,1)走到(n,m),他可以往右边或者往下走,每次到一个点会获得当前的点权值,并将权值和mod 1e4 + 7,当牛牛从不同方式走到(n,m)的时候能获得多少种权值和?

输入描述:

第一行输入正整数n,m(n,m≤100)n,m(n,m leq 100)n,mn,m100

接下来 nnn 行每行有 mmm 个正整数,分别代表aija_{ij}aij(aij≤109)(a_{ij}leq 10^9)aij109

输出描述:

输出一行,表示到(n,m)点的时候的权值和种数

示例1

输入

2 2
1 1
2 2

输出

2

说明

有1+1+2和1+2+2两种

解法:每个点aij只可能由aij -1、ai-1j转移过来,dp[ i ][ j ][ (k + a[ i ][ j ])%mod ] = dp[ i ][ j - 1 ][ k ] | dp[ i - 1 ][ j ][ k ]

代码:

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int mod=1e4+7;
int n,m;
int a[105][105];
bool dp[105][105][mod+5];
int main(){
    cin>>n>>m;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            cin>>a[i][j];
            a[i][j]%=mod;
        }
    }
    dp[1][1][a[1][1]]=1;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            if(i==1&&j==1) continue;
            for(int k=0;k<mod;k++){
                dp[i][j][(a[i][j]+k)%mod]|=dp[i][j-1][k];
                dp[i][j][(a[i][j]+k)%mod]|=dp[i-1][j][k];
            }
        }
    }
    int ans=0;
    for(int k=0;k<mod;k++)
        ans+=dp[n][m][k];
    cout<<ans<<endl;
}

用bitset的写法:

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int mod=1e4+7;
int n,m;
int a[105][105];
bitset<mod>dp[105][105];
int main(){
    cin>>n>>m;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            cin>>a[i][j];
            a[i][j]%=mod;
        }
    }
    dp[0][1]=1;dp[1][0]=1;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            bitset<mod> cnt1=(dp[i][j-1]<<a[i][j])|(dp[i][j-1]>>(mod-a[i][j]));
            bitset<mod> cnt2=(dp[i-1][j]<<a[i][j])|(dp[i-1][j]>>(mod-a[i][j]));
            dp[i][j]=cnt1|cnt2;
        }
    }
    cout<<dp[n][m].count()<<endl;
}



原文地址:https://www.cnblogs.com/xuanzo/p/13714953.html