题目传送门https://www.luogu.com.cn/problem/P1002
前言
什么是dp?(由AI生成)
DP是动态规划(Dynamic Programming)的缩写。动态规划是一种解决问题的算法思想,它通过将问题分解为子问题,并保存子问题的解来解决原问题。DP常用于求解具有重叠子问题和最优子结构性质的问题。
在动态规划中,使用一个状态数组或表格来保存子问题的解。通过填表或者递归的方式,逐步求解子问题,并最终得到原问题的解。动态规划具有时间和空间上的优化,可以大大减少重复计算的次数,提高算法的效率。
动态规划常用于求解最优化问题,如最长递增子序列、背包问题、最短路径等等。它在算法设计和解决实际问题中有广泛的应用。
整体思路
首先它说小兵只能向右方向和下方向移动所以举个例子(手工制作不易,敬请谅解):
这里我们可以假设画红晕的地方是不能走的,那麽我们可以发现画绿叉的地方也是不能走的。
接着我们再来看一下,假如:
1种 | 1种 | 1种 |
1种 | 2种 | 3种 |
1种 | 3种 | 6种 |
以我标红的为例:
他有一种是从上面下来(加上上面的方案数)
还有一种是从左边过来(加上左边的方案数)
由此得到最最最最最重要的:
接下来就比较简单了
求出马能走到的地方,直接封死标记:
const int dx[8]={-1,-2,-2,-1,1,2,2,1};
const int dy[8]={2,1,-1,-2,2,1,-1,-2};
int vis[50][50];
for(int i=0;i<8;i++){
int xx=dx[i]+马的x坐标;
int yy=dy[i]+马的y坐标;
vis[xx][yy]=1;
}
最后再把上面的式子套上就可以了:
for(int i=2;i<=bx;i++){
for(int j=2;j<=by;j++){
if(i==2&&j==2) continue;
if(vis[i][j]==1) continue;
dp[i][j] = dp[i-1][j]+dp[i][j-1];
}
}
!!!注意为了防止马越界,从2开始!
某人提供的六步法(思路概括)
1.找状态确定数组含义
dp[i][j]表示走到i,j的位置可以采用的总方法数
2.找好转移
式子已给出
3.确定你的推导顺序
i : 从2->bx
j : 从2->by
4.确定好初始值
dp[2][2]=1;
5.打印每一个转移结果
不做解释
6.确定你想输出什么
同上
注释代码
#include<bits/stdc++.h>
using namespace std;
int bx,by,hx,hy;
//判断能不能走
int vis[50][50];
long long dp[50][50];
//马的8个方位
const int dx[8]={-1,-2,-2,-1,1,2,2,1};
const int dy[8]={2,1,-1,-2,2,1,-1,-2};
int main(){
//输入
cin>>bx>>by>>hx>>hy;
//防越界
bx+=2;
by+=2;
hx+=2;
hy+=2;
//小兵是蒟蒻,不能吃马
vis[hx][hy] = 1;
//马的控制范围
for(int i=0;i<8;i++){
int xx=dx[i]+hx;
int yy=dy[i]+hy;
vis[xx][yy]=1;
}
//初始值
dp[2][2]=1;
//已做解释~
for(int i=2;i<=bx;i++){
for(int j=2;j<=by;j++){
if(i==2&&j==2) continue;
if(vis[i][j]==1) continue;
dp[i][j] = dp[i-1][j]+dp[i][j-1];
}
}
//输出
cout<<dp[bx][by];
return 0;
}
纯净代码:
#include<bits/stdc++.h>
using namespace std;
int bx,by,hx,hy;
int vis[50][50];
long long dp[50][50];
const int dx[8]={-1,-2,-2,-1,1,2,2,1};
const int dy[8]={2,1,-1,-2,2,1,-1,-2};
int main(){
cin>>bx>>by>>hx>>hy;
bx+=2;
by+=2;
hx+=2;
hy+=2;
vis[hx][hy] = 1;
for(int i=0;i<8;i++){
int xx=dx[i]+hx;
int yy=dy[i]+hy;
vis[xx][yy]=1;
}
dp[2][2]=1;
for(int i=2;i<=bx;i++){
for(int j=2;j<=by;j++){
if(i==2&&j==2) continue;
if(vis[i][j]==1) continue;
dp[i][j] = dp[i-1][j]+dp[i][j-1];
}
}
cout<<dp[bx][by];
return 0;
}