题目:跳跃版图
题目描述
有一个 n×n 的格子,每个格子中有一个非负整数。你的目标是从左上角跳到右下角,每步只能向右或向下跳。格子中的数代表从该格开始跳跃的前进步数,如果某次跳跃会跃出格子界限则该跳跃是禁止的。注意 0 是一个绝对终点,因为从这里无法再移动。
你的任务是统计有多少种合法路径。上图 1 中共有 3 种路径,分别表示在图 2 中。
输入说明
第一行,一个整数 n。
接下来 n 行 n 列,表示格子中的数,所有数的范围在[0,9]中,两个数之间用一个空格隔开。
输出说明
第一行,从左上角到右下角的合法路径数目。
输入样例
4
2 3 3 1
1 2 1 3
1 2 3 1
3 1 1 0
输出样例
3
数据范围
共有 20 组数据,每组 5 分。至少 5 组数据,n<=12。
至少 14 组数据,n<=35。
对于所有数据,3<=n<=100。
类似过河卒的dp,不过需要高精度,李国豪(清华)学长写得高精度赞得很,学一波!
#include<iostream> #include<cstdio> #include<cstring> using namespace std; long long n,x; void in(long long &x) { char c=getchar();x=0; while(c<'0'||c>'9')c=getchar(); while(c>='0'&&c<='9')x=x*10+c-'0',c=getchar(); } struct num { int a[200],l; void clr() { memset(a,0,sizeof(a)); a[0]=1;a[1]=0; l=1; } void operator +=(const num &b) { if(b.l>l) l=b.l; for(int i=1;i<=l;i++) { a[i]+=b.a[i]; a[i+1]+=a[i]/10; a[i]%=10; } if(a[l+1]>0) l++; } void out() { for(int i=l;i>=1;i--) cout<<a[i]; } }f[110][110]; int main() { freopen("jump.in","r",stdin); freopen("jump.out","w",stdout); in(n); for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) f[i][j].clr(); f[1][1].a[1]=1; for(long long i=1;i<=n;i++) for(long long j=1;j<=n;j++) { in(x); if(i+x<=n&&x!=0) f[i+x][j]+=f[i][j]; if(j+x<=n&&x!=0) f[i][j+x]+=f[i][j]; } f[n][n].out(); return 0; }