这几周在学习动态规划,没什么时间更新。
偶然间看到一题,无数牛逼的代码在我心中闪过,脑海中框架已然成形,准备大展拳脚。
注意:不论是数组还是变量都记得开long long!!!
好了,100昏代码如下!
#include<iostream>
#include<vector>
#include<math.h>
typedef long long ll;
using namespace std;
int main(){
ll m, n, a, b;
scanf("%lld %lld %lld %lld", &m, &n, &a, &b);
m++,n++;
vector<vector<ll> > Map(m, vector<ll>(n, 0));
vector<vector<ll> > dp(m, vector<ll>(n, 0));
// 设置障碍物
for(int i = a - 2; i <= a + 2; i++) {
for(int j = b - 2; j <= b + 2; j++) {
if(i >= 0 && i < m && j >= 0 && j < n && (abs(a - i) + abs(b - j) == 3)) {
Map[i][j] = 1;
}
}
}
Map[a][b] = 1;
// 初始化边界
for(int i = 0; i < m; i++){
if(Map[i][0] == 1){
break;
}
dp[i][0] = 1;
}
for(int j = 0; j < n; j++){
if(Map[0][j] == 1){
break;
}
dp[0][j] = 1;
}
// 动态规划计算路径数量
for(int i = 1; i < m; i++){
for(int j = 1; j < n; j++){
if(Map[i][j] == 0) {
dp[i][j] = dp[i-1][j] + dp[i][j-1];
}
}
}
printf("%d", dp[m-1][n-1]);
return 0;
}
外加,可以打印的代码,也如下!!
#include<iostream>
#include<vector>
#include<math.h>
typedef long long ll;
using namespace std;
int main(){
ll m, n, a, b;
scanf("%lld %lld %lld %lld", &m, &n, &a, &b);
m++,n++;
vector<vector<ll> > Map(m, vector<ll>(n, 0));
vector<vector<ll> > dp(m, vector<ll>(n, 0));
// 设置障碍物
for(int i = a - 2; i <= a + 2; i++) {
for(int j = b - 2; j <= b + 2; j++) {
if(i >= 0 && i < m && j >= 0 && j < n && (abs(a - i) + abs(b - j) == 3)) {
Map[i][j] = 1;
}
}
}
Map[a][b] = 1;
// 初始化边界
for(int i = 0; i < m; i++){
if(Map[i][0] == 1){
break;
}
dp[i][0] = 1;
}
for(int j = 0; j < n; j++){
if(Map[0][j] == 1){
break;
}
dp[0][j] = 1;
}
// 动态规划计算路径数量
for(int i = 1; i < m; i++){
for(int j = 1; j < n; j++){
if(Map[i][j] == 0) {
dp[i][j] = dp[i-1][j] + dp[i][j-1];
}
}
}
printf("%d", dp[m-1][n-1]);
//打印dp数组
cout<<"打印dp数组"<<endl;
for(int i=0;i<m;i++){
for(int j=0;j<n;j++){
cout<<" "<<dp[i][j];
}
cout<<endl;
}
//打印Map数组
cout<<"打印Map数组"<<endl;
for(int i=0;i<m;i++){
for(int j=0;j<n;j++){
cout<<" "<<Map[i][j];
}
cout<<endl;
}
return 0;
}
这题就是一个入门dp的不歪滴题。
先说明下dp数组的含义,是走到[i,j]时,有dp[i][j]种走法(就和题目要求的一样)
由于马是不动的,所以可以将马及马の落脚点都看做障碍物,我这里在Map中用“0”代表无障碍,用“1”代表有障碍。
那么和入门的一些dp一样dp数组的递推公式就是当前的dp[i][j]是由他的上面和右面走来的,所以不难得到dp[i][j]=dp[i-1][j]+dp[i][j-1]这个递推公式,而且还要注意因为障碍物的存在,遇到障碍物的时候就应该跳过,并将dp数组相应的值赋值为0,我初始化的时候就已经将dp数组全部初始化为0了,所以就可以省去赋值为0这部操作!
还有再看下遍历的顺序,默认的起始位置就是[0.0],所以就是从上到下,从左到右。
最后,我来补充下对dp数组进行初始化的操作,如果在边界上有障碍物(我就将马和马的落点叫障碍物了)的话,障碍物后的dp数组的值只能是0,因为卒只能向下或向右走。
目前,能讲到的就这么多了,如果代码中哪里不清楚,欢迎在评论区发言,看到必回!!