洛谷:P1002 [NOIP2002 普及组] 过河卒

这几周在学习动态规划,没什么时间更新。

偶然间看到一题,无数牛逼的代码在我心中闪过,脑海中框架已然成形,准备大展拳脚。

注意:不论是数组还是变量都记得开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,因为卒只能向下或向右走。

目前,能讲到的就这么多了,如果代码中哪里不清楚,欢迎在评论区发言,看到必回!!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值