dp基礎之網格問題

2021-08-31 03:51:32 字數 4786 閱讀 1562

**及注釋如下:

#!/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 問題分析 可以先對金字塔進行變形,如上。對於數字金字...