题目描述
– 某城市的街道是一个很规整的矩形网格(见下图),有 M 条南北向的纵街,N 条东西向的横街。现要从西南角的 A 走到东北角的 B,最短的走法共有多少种?输入
– 输入文件 Sline.in,一行,两个数 M,N,其中 2 < M,N <= 800- 输出
– 输出文件 sline.out,输出最短路的走法总数. - 样例输入
7 5 - 样例输出
210 - 数据范围限制
【限制】
– 对于 30%的数据, 2 < M,N <= 30;
– 对于 60%的数据, 2 < M,N <= 100;
– 对于 100%的数据, 2 < M,N <= 800;
题解:
- 这道题是高精度里的dp
- 首先,走到一个点的方法总数,就等于走到上一个点的方法之和 所以说:
dp[i][j]=dp[i-1][j]+dp[i][j-1]
-- 然后发现答案最大的一个有450多位,就套一个高精度加法就行了
-- 但是!!! 开始我就直接用最简单的高精度,竟然平生第一次爆空间!!!
-- 所以还要压位(在数组一个元素里存更多的位数)
-- 最后注意要把用来记录进位的变量也定义为longlong(预防迷之错误)
代码:
#include<iostream>
#include<cmath>
#include<cstring>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
using namespace std;
const int MAXN=805;
const long long mod=1e16;
int n,m;
struct hehe {
long long A[50];
int l;
hehe() {
for(int i=0; i<=39; i++)
A[i]=0;
l=0;
}
};
hehe step[MAXN][MAXN];
void add(hehe &a,hehe &b,hehe &c) {
long long x=0;
while(c.l<=a.l||c.l<=b.l) {
c.A[c.l]=a.A[c.l]+b.A[c.l]+x;
x = 0;
if(c.A[c.l]>=mod) {
x=c.A[c.l]/mod;
c.A[c.l]%=mod;
}
c.l++;
}
c.A[c.l]=x;
while(!c.A[c.l])
c.l--;
}
int main() {
// freopen("sline.in","r",stdin);
// freopen("sline.out","w",stdout);
cin>>m>>n;
step[0][1].A[0]=1;
step[0][1].l=0;
for(int i=1; i<=n; i++)
for(int j=1; j<=m; j++)
add(step[i-1][j],step[i][j-1],step[i][j]);
for(int i=step[n][m].l; i>=0; i--)
if(i==step[n][m].l)
cout<<step[n][m].A[i];
else
printf("%016lld",step[n][m].A[i]);
return 0;
}