#dp#洛谷 3473 [POI2008] UCI-The Great Escape JZOJ 4019 Path
题目
\(n*m\)的地图,计算从\((n,1)\)到第\(x\)列的第\(y\)行的路径条数\(\bmod k\) ,
走过的点不能再走,转弯只能向右转。转弯完之后必须往前走一格
分析
可以发现,走的过程类似于一个矩形,这可以列一个\(dp\)方程
关于滚动数组采用枚举行数加列数再枚举行数,接着枚举左下角得到右上角的坐标
然后在走的时候要判断这一横竖是否有障碍
代码
#include <cstdio>
#define rr register
using namespace std;
int n,m,mod,zy,zx,rw[101][101],cl[101][101],dp[2][4][101][101][101];
inline void Mo(int &A,int x,int y){A=x+y>=mod?x+y-mod:x+y;}
inline bool cor(int x,int y){return x==zx&&y==zy;}
signed main() {
scanf("%d%d%d%d%d",&n,&m,&mod,&zy,&zx);
for (rr int i=1;i<=n;++i)
for (rr int j=1;j<=m;++j){
rr char c=getchar();
while (c!='+'&&c!='*') c=getchar();
rw[i][j]=rw[i][j-1]+(c=='*'),
cl[i][j]=cl[i-1][j]+(c=='*');
}
for (rr int S=2;S<=n+m;++S)
for (rr int i=1;i<S;++i){
rr int j=S-i;
for (rr int lx=1;lx<=zx&&lx<=n-i+1;++lx)
for (rr int ly=1;ly<=zy&&ly<=m-j+1;++ly){
rr int rx=lx+i-1,ry=ly+j-1;
if (rx<zx||ry<zy) continue;
Mo(dp[S&1][0][lx][ly][rx],dp[(S&1)^1][0][lx][ly][rx],(rw[lx][ry]==rw[lx][ly-1])*(dp[(S&1)^1][1][lx+1][ly][rx]+cor(lx,ry)));
Mo(dp[S&1][1][lx][ly][rx],dp[(S&1)^1][1][lx][ly][rx-1],(cl[rx][ry]==cl[lx-1][ry])*(dp[(S&1)^1][2][lx][ly][rx]+cor(rx,ry)));
Mo(dp[S&1][2][lx][ly][rx],dp[(S&1)^1][2][lx][ly+1][rx],(rw[rx][ry]==rw[rx][ly-1])*(dp[(S&1)^1][3][lx][ly][rx-1]+cor(rx,ly)));
Mo(dp[S&1][3][lx][ly][rx],dp[(S&1)^1][3][lx+1][ly][rx],(cl[rx][ly]==cl[lx-1][ly])*(dp[(S&1)^1][0][lx][ly+1][rx]+cor(lx,ly)));
}
}
return !printf("%d",dp[(n+m)&1][3][1][1][n]);
}