【DP】骑士游历IV

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;
}



猜你喜欢

转载自blog.csdn.net/SSL_wujiajie/article/details/82776216
今日推荐