python学习之路——DP算法初试

这次的题目是这样的:

  假设有一个6*6的棋盘,每个格子里面有一个奖品(每个奖品的价值在100到1000之间),现在要求从左上角开始到右下角结束,每次只能往右或往下走一个格子,所经过的格子里的奖品归自己所有。问最多能收集价值多少的奖品。

           
           
           
           
           
           

  最先看到这个问题的时候脑子里面的立马出现许多的脑洞:暴力、二叉树、图中的带权路径等等。但是想来想去没有想出个所以然来。偶然在一本算法书上看见了讲DP算法(动态规划)的部分,仔细一想,貌似能够用在这里的。

  DP算法适用于前一步的决策影响后一步决策的问题中。本题蓝色方块的决策取决于其左边和上面的最优决策,因此,对于蓝色部分a[i][j]只需要取max{a[i-1][j],a[i][j-1]}+a[i][j];对于白色部分,只受左边或者上面的决策影响,因此对于横向的a[i][j]应该取a[i][j-1]+a[i][j],对于纵向的a[i][j]应该取a[i-1][j]+a[i][j]。其实DP能够解决的问题还有很多,我相信这也是一个特别有用的算法,强烈建议阅读学习使用。

 

tips:代码中涉及python中二维数组的初始化和赋值,可以用列表推导式初始化。

代码:

 1 import random
 2 count=0
 3 a=[[0 for i in range(6)]for i in range(6)]
 4 print("随机生成一个6*6的二维数组做为棋盘中的权值:")
 5 for i in range(6):
 6     for j in range(6):
 7         a[i][j] = random.randint(100, 1000)
 8         print('%2d'%a[i][j],end=" ")
 9         count+=1
10         if count%6==0:
11             print("\n")
12 for i in range(1,6):
13     a[0][i]=a[0][i-1]+a[0][i]
14     a[i][0]=a[i-1][0]+a[i][0]
15 for i in range(1,6):
16     for j in range(1,6):
17         a[i][j]=max(a[i-1][j],a[i][j-1])+a[i][j]
18 print("变化后的数组:")
19 for i in range(6):
20     for j in range(6):
21         print('%2d'%a[i][j],end=" ")
22         count+=1
23         if count%6==0:
24             print("\n")
25 print("最终得最大值为%d" %a[5][5])

运行结果:

 


 

    当然,在自己做出来之前,不免询问了一下我们的度娘,也得到了一种暴力解法,无奈用的递归解决的,太暴力太烧脑,想了好久都没想通,这里将原c++版的代码改写成了python的代码供大家学习思考。

#6*6的棋盘求最大路径
import random
global count
totalprice=0
tmp=0
count=0
a=[[0 for i in range(6)]for i in range(6)]
b=[[0 for i in range(6)]for i in range(6)]
next=[[1,0],[0,1]]
def find(x, y):
    global totalprice
    global tmp
    totalprice+=a[x][y]
    if x==5 and y==5:
        if totalprice>tmp:
            tmp=totalprice
            return
    for k in range(2):
        tx=x+next[k][0]
        ty=y+next[k][1]
        if tx<0 or tx>5 or ty<0 or ty>5:
            continue
        if b[tx][ty]==0:
            b[tx][ty]=1
            find(tx,ty)
            totalprice-=a[tx][ty]
            b[tx][ty]=0
    return
for i in range(6):
    for j in range(6):
        a[i][j] = random.randint(1, 100)
        print('%2d'%a[i][j],end=" ")
        count+=1
        if count%6==0:
            print("\n")
b[0][0]=1
find(0,0)
print(tmp)

 

posted @ 2017-04-22 21:40  小丶诺  阅读(5368)  评论(0编辑  收藏  举报