Description
如下图所示有m*n(n,m<=100)一个棋盘,在棋盘左下角的A(1,1)点,有一个中国象棋〈马〉,并约定马走的规则:
①走日字;②只能向右走。
如图所示,图中有一障碍区域,不能通过,问从左下角到右上角有多种不同的方法。
Input
第一行:棋盘大小
第二行:前两个数为障碍区域的左下角从标,后两个数为右上角坐标
Output
总共有多少方案。
Sample Input
100 100
10 10 20 20
Sample Output
3445139108919873944830950428668
思路
动态规划。因为结果大,所以要压位,否则数组管你开多大,反正就是炸。
#include<iostream>
#include<cstdio>
using namespace std;
const int dx[5]={0,2,1,-1,-2};
const int dy[5]={0,-1,-2,-2,-1};//方向
int n,m;//大小
int f[105][105][11];
bool a[105][105]={0};
bool check(int x,int y)//判断是否超界
{
if(x<1 || x>n || y<1 || y>m)return 0;
else if(a[x][y]==1)return 0;
else return 1;
}
void add(int x1,int y1,int x2,int y2)
{
int g=0,k;
for(int i=10;i>=1;i--)//因为有压位,所以才只循环了十次
{
k=f[x1][y1][i]+f[x2][y2][i]+g;
f[x1][y1][i]=k%10000000;
g=k/10000000;//记得压位,否则数组都会炸
}
}
int main()
{
int x1,y1,x2,y2;
scanf("%d%d",&n,&m);
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
for(int i=x1;i<=x2;i++)
for(int j=y1;j<=y2;j++)
a[i][j]=1;//把障碍区域赋值为不能走
f[1][1][10]=1;
for(int j=1;j<=m;j++)
for(int i=1;i<=n;i++)//必须是一列一列,否则错了
for(int k=1;k<=4;k++)
if(check(i+dx[k],j+dy[k]))
add(i,j,i+dx[k],j+dy[k]);//如果走可以就加一
int k=1;
while(f[n][m][k]==0 && k<10)k++;
printf("%d",f[n][m][k++]);
for (int i=k;i<=10;i++)
{
if(f[n][m][i]<10) printf("000000");
else if(f[n][m][i]<100) printf("00000");
else if(f[n][m][i]<1000) printf("0000");
else if(f[n][m][i]<10000) printf("000");
else if(f[n][m][i]<100000) printf("00");
else if(f[n][m][i]<1000000) printf("0");//压位
printf("%d",f[n][m][i]);
}
return 0;
}