2018.3.4 sline

4.最短路线(sline.pas/c/cpp) 
题目描述 某城市的街道是一个很规整的矩形网格(见下图),有 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;

分界线---------------------------------------------------------------------------------------------------------------------------

图好像下不来,嘛。

这本是一道非常单纯的找规律递推题,然而狠心的出题者把数据开的特别大,这就很难受。

总而言之要用高精度。

要找出一个规律,第i行第j列的方法数等于第i - 1行第j列和第i行第j - 1列的加和。

通项公式 f[i][j] =f[i - 1][j] + f[i][j - 1];

我自己写了一份近似托哥思路的写法,但是果然有什么迷之错误。。

#include<bits/stdc++.h>
using namespace std;
const long long UP = 1e18;
const int w = 18; 
const int MAXN = 81; 
struct M{
long long num[MAXN];
long long len;
long long & operator [] (int x) { return num[x];}
M operator + (M &Else)
{
M r = *this;
int end = max(len,Else.len);
for(int i = 0;i < end;i++)
{
r[i] += Else[i];
if(r[i] >= UP)
{
r[i + 1] += r[i] / UP;
r[i] = r[i] % UP;
}
}
if(r[end]) ++end;
r.len = end;
return r;
}
M() : num() {} 
}f[800][800];
int main()
{
int n,m;
cin >> m >> n;
// f[0][0][0] = 1;
// f[0][0].len = 1;
for(int i = 1;i <= n; i++)
{
f[i][0][0] = 1;
f[i][0].len = 1;
}
for(int i = 1;i <= m;i++)
{
f[0][i][0] = 1;
f[0][i].len = 1;
}
for(int i = 1;i <= n;i++)
{
for(int j = 1;j <= m;j++)
{
f[i][j] = f[i - 1][j] + f[i][j - 1];
}
}
printf("%lld",f[n][m][f[n][m].len - 1]);
for(int i = f[n][m].len - 2;i >= 0;i--)
{
printf("%0*lld",w,f[n][m][i]);
}
return 0;

于是就用平民算法写了一遍也不知过不过得了:

#include<bits/stdc++.h>
using namespace std; 
const long long UP = 1e7;
const int w = 7; 
int m,n,ans; 
int a[802][802][81];
void sum(int x,int y,int xx,int yy,int q,int w)
{
    int qq = 0; 
    for (int i=1;i<=81;i++)
    {
        a[q][w][i] += qq + a[x][y][i] + a[xx][yy][i]; 
        qq = a[q][w][i]/UP; 
        a[q][w][i] %= UP; 
    }
}
int main()
{
    scanf("%d%d",&m,&n); 
   for (int i = 1;i <= 800;i++)
    a[i][1][1] = a[1][i][1] = 1; 
   for (int i = 2;i <= n;i++)
    for (int j = 2;j <= m;j++)
     sum(i-1,j,i,j-1,i,j); //规律
  int tg=81; 
  while (tg > 1 && a[n][m][tg] == 0) tg--;    
  printf("%d",a[n][m][tg]);
  for (int i = tg-1;i >= 1;i--)
  {
     printf("%0*d",w,a[n][m][i]);
  }
}

猜你喜欢

转载自blog.csdn.net/chang_yl/article/details/79436494