**及注釋如下:
#!/usr/bin/python
def get_case(m,n):
#m,n分別為網格的行列數
#建立乙個列表
#f[i][j]表示從左上開始到第i行第j列的點的路徑數
f = [[0 for x in range(n)] for y in range(m)]
#f[0][0]表示初始情況
f[0][0] = 1
for i in range(m):
#先行for j in range(n):
#後列#邊界條件,在最上面行或者在最左邊的列
if i == 0 or j == 0:
f[i][j] = 1
else:
# 上面走下來+左邊走過來
f[i][j] = f[i-1][j]+f[i][j-1]
return f[m-1][n-1]
m = 3
n=4print(get_case(m,n))
#結果:10
**及注釋如下:
def get_case(a):
m,n = len(a),len(a[0])
if m == 0 or n == 0:
return 0
f = [[0 for x in range(n)] for y in range(m)]
for i in range(m):
for j in range(n):
#若有障礙,則路徑數字0
if a[i][j] == 1:
f[i][j] == 0
else:
#無障礙
if i == 0 and j == 0:
#初始條件,f[0][0]=1
f[i][j] = 1
else:
if i-1 >= 0:
# 從上邊走下來
f[i][j] += f[i-1][j]
if j-1 >= 0:
# 從左邊走過來
f[i][j] += f[i][j-1]
return f[m-1][n-1]
a = [[0,0,0],[0,1,0],[0,0,0]]
print(get_case(a))
輸出為2
注釋及**如下:
import sys
def shortest_path(a):
#f[i][j]表示從[0][0]到[i][j]最小數字和
m,n = len(a),len(a[0])
if m == 0 or n==0:
return 0
f = [[0 for x in range(n)] for y in range(2)]
#空間優化old表示i-1行,now是i行
old ,now = 1,0
for i in range(m):
old ,now = now ,old #old是i-1行,now是i行
for j in range(n):
#初始條件f[0][0]=a[0][0]
if i==0 and j==0:
f[now][j] == a[i][j]
continue
f[now][j] = a[i][j]
#如果上面有一行,即不是第0行
if i > 0:
temp1 = f[old][j]
else:
temp1 = sys.maxsize
#如果有左邊一列,即不是第1列
if j > 0:
temp2 = f[now][j-1]
else:
temp2 = sys.maxsize
f[now][j] += min(temp1,temp2)
# if temp1 < temp2:
# f[now][j] += temp1
# else:
# f[now][j] += temp2
return f[now][n-1]
a = [[1,2,2],[1,2,3],[1,1,1]]
print(shortest_path(a))
結果:4
注:時間複雜度為o(mn),空間複雜度是o(2n),其實,空間還可以優化到o(n)
**及注釋如下:
#我們考慮每個格仔不同方向上能炸死的敵人數,返回能炸死最多的那個敵人數
def bomb_enemies(a):
m,n = len(a),len(a[0])
#先初始化最後結果是0
result = 0
if m == 0 and n == 0:
return 0
f = [[0 for x in range(n)] for y in range(m)]
#res[i][j]表示在格仔[i][j]可以炸死四個方向的敵人數,初始化為0
res = [[0 for x in range(n)] for y in range(m)]
#f[i][j]表示格仔[i][j]向上能炸死的人數
for i in range(m):
for j in range(n):
#如果是牆,我們假設沒有敵人
if a[i][j] == 'w':
f[i][j] = 0
else:
#有敵人的情況
#先初始化為0
f[i][j] = 0
#若格仔[i][j]是敵人,先置為1,因為是從上到下累加
if a[i][j] == 'e':
f[i][j] = 1
if i-1 >= 0:#格仔[i][j]上面有格仔
#累加f[i][j] += f[i-1][j]
#將向上能炸死的敵人數累加到res裡
res[i][j] += f[i][j]
#f[i][j]表示格仔[i][j]向下能炸死的人數
#這裡應該從下向上計算f[i][j],即先從最後一行開始計算
for i in range(m-1,-1,-1):
for j in range(n):
#如果是牆,我們假設沒有敵人
if a[i][j] == 'w':
f[i][j] = 0
else:
#有敵人的情況
#先初始化為0
f[i][j] = 0
#若格仔[i][j]是敵人,先置為1,因為是從下到上累加
if a[i][j] == 'e':
f[i][j] = 1
if i+1 < m:#格仔[i][j]下面有格仔
#累加f[i][j] += f[i+1][j]
#將向下能炸死的敵人數累加到res裡
res[i][j] += f[i][j]
#同理求向左和向右的情況
#f[i][j]表示格仔[i][j]向左能炸死的人數
for i in range(m):
for j in range(n):
#如果是牆,我們假設沒有敵人
if a[i][j] == 'w':
f[i][j] = 0
else:
#有敵人的情況
#先初始化為0
f[i][j] = 0
#若格仔[i][j]是敵人,先置為1,因為是從上到下累加
if a[i][j] == 'e':
f[i][j] = 1
if j-1 >= 0:#格仔[i][j]左邊有格仔
#累加f[i][j] += f[i][j-1]
#將向左能炸死的敵人數累加到res裡
res[i][j] += f[i][j]
#f[i][j]表示格仔[i][j]向右能炸死的人數
#先從最後一列開始計算
for i in range(m):
for j in range(n-1,-1,-1):
#如果是牆,我們假設沒有敵人
if a[i][j] == 'w':
f[i][j] = 0
else:
#有敵人的情況
#先初始化為0
f[i][j] = 0
#若格仔[i][j]是敵人,先置為1
if a[i][j] == 'e':
f[i][j] = 1
if j+1 < n:#格仔[i][j]右邊有格仔
#累加f[i][j] += f[i][j+1]
#將向右能炸死的敵人數累加到res裡
res[i][j] += f[i][j]
#此時res[i][j]表示的是格仔[i][j]向四個方向能炸死的敵人數
for i in range(m):
for j in range(n):
#如果是空地
if a[i][j] == '0' :
#如果空地能炸死的敵人有更大的數量,則更新最終結果result
if res[i][j] > result:
result = res[i][j]
return result
a = [['0','e','0','0'],['e','0','w','e'],['0','e','0','0']]
print(bomb_enemies(a))
結果是3
注:如果給出的矩陣是方陣,不用四個迴圈來計算四個方向的敵人數,讓方陣轉向3次即可=-= dp期望之網格遊戲
有乙個遊戲平板上面有n m個格仔,一開始每個格仔都是關閉的,每個格仔裡面都有乙個標記 已知每種標記恰好出現兩次,也就是一共有n m 2種標記 規定一次移動為依次 one by one不是同時 開啟一對格仔檢視裡面的標記,如果標記不一樣,格仔會自動關閉,但是你的記憶是超強了,看過了就不會忘,如果標記是...
網格染色問題
有乙個網格,在初始狀態下所有網格都是空白的。現有如下操作 執行n次操作,每次選擇座標對應的那一行和一列,在該行或該列上選擇兩個端點網格,將兩個端點網格間的所有網格 包括端點網格 都染色。具體染色規則 如果兩個網格座標 x1,y1 和 x2,y2 中橫座標x1 x2,則把這一列所有網格都染色,如果縱座...
DP問題之數塔問題
問題描述 考慮下面的數字金字塔,寫乙個程式來計算從最高點開始,在底部任意處結束經過的數字和最大,每一步可以走到左下和右下的點。73 8 8 1 0 2 7 4 4 4 5 2 6 5 變形後 3 8 8 1 0 2 7 4 4 4 5 2 6 5 問題分析 可以先對金字塔進行變形,如上。對於數字金字...