#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]);
}
posted @ 2020-02-10 18:07  lemondinosaur  阅读(235)  评论(0编辑  收藏  举报