本文最后更新于 35 天前,其中的信息可能已经有所发展或是发生改变。
视频演示
将棋盘问题抽象成数组(dp问题—一般简称DP动态规划是一种通过把原问题分解为相对简单的子问题的方式求解复杂问题的方法。)。如视频所言,第一考虑没马情况去推测每个元素的值即为上加左(只能向下或者向右移动故本格值即为前一步之和)此时即可求出没马情况下到达0点到达B点的路径数目。第二加上马那么将对方马的守护点即为其他数字(为0)当遍历到0时则终止运算。
代码演示
//初次尝试的低端代码
#include<iostream>
using namespace std;
int main()
{
long long desk[30][30] = {0};
int n,m,x,y;
cin>>n>>m>>x>>y;
for(int i=0;i<=n;i++){
for(int j=0;j<=m;j++){
desk[i][j]=1;
}
}
desk[y][x] = 0;
if(y + 2 < m && x - 1 >= 0)desk[y+2][x-1] = 0;
if(y + 2 < m && x + 1 < n)desk[y+2][x+1] = 0;
if(y - 2 >= 0 && x - 1 >= 0)desk[y-2][x-1] = 0;
if(y - 2 >= 0 && x + 1 < n)desk[y-2][x+1] = 0;
if(y + 1 < m && x - 2 >= 0)desk[y+1][x-2] = 0;
if(y + 1 < m && x + 2 < n)desk[y+1][x+2] = 0;
if(y - 1 >= 0 && x - 2 >= 0)desk[y-1][x-2] = 0;
if(y - 1 >= 0 && x + 2 < n)desk[y-1][x+2] = 0;
for(int i=0;i<=n;i++){
for(int j=0;j<=m;j++){
if(i==0&&j==0){continue;}
if(desk[i][j]==0){continue;}
if(i==0){desk[i][j]=desk[i][j-1];}
else if(j==0){desk[i][j]=desk[i-1][j];}
else{desk[i][j]=desk[i-1][j] + desk[i][j-1];}
}
}
cout<<desk[n][m]<<endl;
return 0;
}
主体思路:在一场二维数组中展开问题,第一步先布置局面desk布局0,第二步输入n,m控制操作实时局面布局1和x,y马与马脚确定值,(通过很多个if来保证不越界)第三步,分类讨论,0-0不改变,碰到标记点0时也是跳过,在顶侧和左侧边的特殊处理(左侧复制上侧,反之亦然),第四步,最后是递推的主体[I][J]等于上侧数值+左侧数值。最后调取[N][M]即可
//优雅永不过时
#include<iostream>
using namespace std;
const int fx[] = {0, -2, -1, 1, 2, 2, 1, -1, -2};
const int fy[] = {0, 1, 2, 2, 1, -1, -2, -2, -1};
int bx, by, mx, my;
long long f[30][30];
bool s[30][30];
int main(){
cin >> bx >> by >> mx >> my;
bx += 2; by += 2; mx += 2; my += 2;
f[2][1] = 1;
s[mx][my] = 1;
for(int i = 1; i <= 8; i++) s[mx + fx[i]][my + fy[i]] = 1;
for(int i = 2; i <= bx; i++){
for(int j = 2; j <= by; j++){
if(s[i][j]) continue;
f[i][j] = f[i - 1][j] + f[i][j - 1];
}
}
cout << f[bx][by] << endl;
return 0;
}
主体思路:1,长变量数组编入马脚的xy值后面用for循环来同一赋值避免屎山代码的出现;2.关键点在于设置两个布局(一是用来递推操作的longlong数组,二是用来判断马脚的布尔类型数组)3.关键点在于将数值输入自增2避免后续考虑是否越界,简单的一部杀死上面的多个if,3.设置起始点f[2][1]=1,开始给布尔数组赋值。4.遍历开始筛选,只有两个筛选对象,1是马脚(跳过),2是非马脚(递推)。巧妙的不像话。