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
Hint
样例1解释:
按上述走法,取到的数之和为1+2+(-1)+4+3+2+(-1)+(-1)=9,可以证明为最大值。
注意,上述走法是错误的,因为第2行第2列的方格走过了两次,而根据题意,不能经过已经走过的方格。
另外,上述走法也是错误的,因为没有走到右下角的终点。
样例2解释:
按上述走法,取到的数之和为(-1)+(-1)+(-3)+(-2)+(-1)+(-2)=-10,可以证明为最大值。因此,请注意,取到的数之和的最大值也可能为负数。
数据范围:
- 对于 20%20% 的数据,n,m≤5。
- 对于 40%40% 的数据,n,m≤50。
- 对于 70%70%的数据,n,m≤300。
- 对于 100%100%的数据,1≤n,m≤1e3。方格中整数的绝对值不超过 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; }