过马卒问题【python】[最细过程],其他语言的同学也欢迎来看

解题思路(解题要求)

  1. 要知道马是走日字的(不会吧,不会吧,不会有人不知道马是走日字的吧(bushi))

  2. 一开始没有注意到需要多开店数组的长度所以吃了很大的亏,虽然开大数组会额外占用内存,但是真的不亏(就算是以吃内存为主的python也一样)

  3. 知道动态规划(其实只要知道dp[i][j] == dp[i - 1][j] + dp[i - 1][j]就可以了)

思考路程(作死路程)

  • 定义一个cheakbored的二维数组
cheakbroad = [[0 for i in range(24)] for j in range(24)]
  • 再将图里面的马的坐标输入进去,
    同时推出可以攻击的位置
    并将这些位置标记,
    标记的方式随你自己,可以通过变为1或者-1
a,b,m,n = map(int,input().split())
cheakbroad[m + 2][n + 2] = 2
cheakbroad[m][n + 1] = 1
cheakbroad[m + 1][n] = 1
cheakbroad[m + 4][n + 1] = 1
cheakbroad[m + 4][n + 3] = 1
cheakbroad[m][n + 3] = 1
cheakbroad[m + 1][n + 4] = 1
cheakbroad[m + 3][n] = 1
cheakbroad[m + 3][n + 4] = 1
0123456
1aa
2aa
3h
4aa
5aa
6f

然后就开始了难点了,递归,动态规划,


我们开大的二维数组的目的就是为了考虑更少的边界情况,第一个问题就在于,如果这个卒一开始就被马这个地方覆盖的话,那么就直接输出0,因为你动都动不了,就乖乖被吃吧。

考虑到这样的情况,那么我们就可以展开递推式了,
dp[i][j] = dp[i - 1][j] + dp[i][j - 1]
首先展开,将最右边和最下面都变为1,(前提是没有遇到攻击点和马)
如果遇到了,那么包括这个点之后的情况就全部变为0。

dp = [[0 for row in range(24)] for roj in range(24
if cheakbroad[2][2] != 0 or cheakbroad[a + 2][b + 2] != 0:
    print(0)
else:
    for i in range(2,a + 3):
        if cheakbroad[i][2] != 0:
            break
        else:
            dp[i][2] = 1
    for j in range(2,b + 3):
        if cheakbroad[2][j] != 0:
            break

再根据二维数组的遍历原则,即一个不动,内部动的原则

  1. 假设我们是一个一个向下遍历的,如果在遍历过程中下一个是a或者h,那么则,在进行判断,因为只有可能是两种情况,右边是危险点或不是危险点(危险就是a或者h的点)
  2. 如果是的话,就将这个点变为0,不是就照常
  3. 如果这个点就是危险点本身,那么就直接变为0
  4. 不需要太注意第一个题解所说的遇到危险点变为j - 2,i - 2,自上而下的遍历是不需要的~~(高傲)~~

~~ 源代码 ~~(废物写了四个小时的)

cheakbroad = [[0 for i in range(24)] for j in range(24)]#构造二维数组
dp = [[0 for row in range(24)] for roj in range(24)]
a,b,m,n = map(int,input().split())#读入数据
cheakbroad[m + 2][n + 2] = 2
cheakbroad[m][n + 1] = 1
cheakbroad[m + 1][n] = 1
cheakbroad[m + 4][n + 1] = 1
cheakbroad[m + 4][n + 3] = 1
cheakbroad[m][n + 3] = 1
cheakbroad[m + 1][n + 4] = 1
cheakbroad[m + 3][n] = 1
cheakbroad[m + 3][n + 4] = 1#标记所有的特殊点
if cheakbroad[2][2] != 0 or cheakbroad[a + 2][b + 2] != 0:#考虑边界情况
    print(0)
else:
    for i in range(2,a + 3):#完成初始化
        if cheakbroad[i][2] != 0:
            break
        else:
            dp[i][2] = 1
    for j in range(2,b + 3):
        if cheakbroad[2][j] != 0:
            break
        else:
            dp[2][j] = 1
    for j in range(3,b + 3):#开始遍历
        for i in range(3,a + 3):
            if cheakbroad[i + 1][j] == 1 or cheakbroad[i + 1][j] == 2:
                if cheakbroad[i][j + 1] == 1 or cheakbroad[i][j + 1] == 2:
                    dp[i][j] = 0
                else:
                    dp[i][j] = dp[i - 1][j] + dp[i][j - 1]
            if cheakbroad[i][j] == 1 or cheakbroad[i][j] == 2:
                    dp[i][j] = 0
            else:
                    dp[i][j] = dp[i - 1][j] + dp[i][j - 1]
    print(dp[a + 2][b + 2])

如果对您有帮助的话可以点个赞吗?
๑乛◡乛๑

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

菜狗原来是我自己

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值