给定一个n*m的网格图,图上有一个起点和一个终点(起点和终点处没有障碍),以及若干障碍,对于每个数字0-9都将会给出一对数(ai,bi)。对于一个数t,我们从高位到低位扫一遍,对于t的每一个数字i将当前位置行加上ai列加上bi,若从起点开始在模拟过程中能不走出边界且不走到障碍最终到达终点,就说数t对于当前网格图合法。问区间[L,R]内合法的数t个数有多少,答案对1,000,000,007取模。
中途到达终点不算。移动是瞬间完成的。
输入格式:
第一行4个整数n、m、L、R,表示网格图的长、宽,询问区间的左、右边界。
接下来n行每行m个字符,对应了n*m的网格图, 表示没有障碍,*表示障碍,1表示起点,2表示终点,3表示起点和终点重合。
接下来10行每行2个整数ai,bi,按顺序分别对应数字0-9。
输出格式:
输出一个整数ans,表示合法的数字个数。
样例输入:
样例输出:
数据范围:
20%的数据1<=L<=R<=10000。
40%的数据1<=L<=R<=1,000,000,000且R-L<=1000000。
60%的数据1<=L<=R<=10^18。
另有10%的数据所有ai=bi=0。
100%的数据0<n,m<=50,|ai|<=n,|bi|<=m,1<=L<=R<=10^500且无前导0。
时间限制:
1s
空间限制:
256M
提示:
123符合要求。
有点沙茶,写了暴力之后写了个10分的高精度。。。数位DP比高精度好写的多啊。。
f[pos][x][y][zero]代表倒数第pos步在x,y 前面有没有前导零。
然后直接记忆化无脑搜索就行了。
#include <cstdio>
#include <cstring>
#include <algorithm>
#define rep(i,l,r) for (int i=l;i<=r;++i)
#define per(i,r,l) for (int i=r;i>=l;--i)
const int MOD=1000000007;
int n,m;
char map[55][55];
int dx[10],dy[10];
int sx,sy,tx,ty;
#define can(x,y) ((x<=n&&x>=1&&y<=m&&y>=1)&&map[x][y]!='*')
bool check(char *x){
int len=strlen(x+1);
int fuck=sx,shit=sy;
rep(i,1,len){
fuck+=dx[x[i]-'0'];
shit+=dy[x[i]-'0'];
if (!can(fuck,shit)) return false;
}
return fuck==tx&&shit==ty;
}
int f[505][55][55][2];int a[505];
int dfs(int pos,int x,int y,bool lim,bool zero){
if (!can(x,y)) return 0;
if (pos<=0) return !zero&&x==tx&&y==ty;
if (!lim&&~f[pos][x][y][zero]) return f[pos][x][y][zero];
int top=lim?a[pos]:9;int res=0;
rep(i,0,top){
if (i==0&&zero){(res+=dfs(pos-1,x,y,lim&&i==top,true))%=MOD;continue;}
(res+=dfs(pos-1,x+dx[i],y+dy[i],lim&&i==top,false))%=MOD;
}
return lim?res:(f[pos][x][y][zero]=res);
}
int count(char *x){
int len=strlen(x+1);
rep(i,1,len) a[i]=x[len-i+1]-'0';
return dfs(len,sx,sy,1,1);
}
char L[505],R[505];
int main(){
memset(f,-1,sizeof f);
scanf("%d%d",&n,&m);
scanf("%s%s",L+1,R+1);
rep(i,1,n) rep(j,1,m){
char& c=map[i][j];
for (c=getchar();c!='1'&&c!='2'&&c!='3'&&c!='*'&&c!=' ';c=getchar());
if (c=='1') sx=i,sy=j;
if (c=='2') tx=i,ty=j;
if (c=='3') sx=tx=i,sy=ty=j;
}
rep(i,0,9) scanf("%d%d",&dx[i],&dy[i]);
printf("%d\n",((count(R)-count(L)+check(L))%MOD+MOD)%MOD);
}