資源限制
時間限制:1.0s 記憶體限制:256.0mb
問題描述
設有nn的方格圖(n<=10),我們將其中的某些方格中填入正整數,而其他的方格中則放入數字0。
某人從圖的左上角的a 點(1,1)出發,可以向下行走,也可以向右走,直到到達右下角的b點(n,n)。在走過的路上,他可以取走方格中的數(取走後的方格中將變為數字0)。
此人從a點到b 點共走兩次,試找出2條這樣的路徑,使得取得的數之和為最大。
輸入格式
輸入的第一行為乙個整數n(表示nn的方格圖),接下來的每行有三個整數,前兩個表示位置,第三個數為該位置上所放的數。一行單獨的0表示輸入結束。
輸出格式
只需輸出乙個整數,表示2條路徑上取得的最大的和。
樣例輸入
82 3 13
2 6 6
3 5 7
4 4 14
5 2 21
5 6 4
6 3 15
7 2 14
0 0 0
樣例輸出
67
/這個是我最開始錯誤的思路:遞迴做法!事實證明不能得出結果 !!
#include
#include
#include
#include
using
namespace std;
int ans =0;
int cot =0;
void
func
(int a[
10],int x,
int y,
int n)
else}if
(x == n)
if(y == n)
a[i+1]
[j]>a[i]
[j+1]?
func
(a,i+
1,j,n)
:func
(a,i,j+
1,n);}
intmain()
func
(a,1,1
,n);
return0;
}
1、既然是多執行緒動態規劃,那麼我們要不用考慮每步怎麼走,要想如何獲得每一步得結果,即只要考慮走到每一步得情況下權值是多少,並且取每一步能獲得的最大權值來相加和,所以我們可以把本題看做兩個人同時從(1,1)走到(n,n),但是要注意:當兩個人某時走到同一座標時,權值只能加和一次!
2、首先我們要用到乙個四維陣列dp[21][21][21][21]來記錄權值的加和;
dp[i][j][k][l]中 i表示第乙個人的x座標,j表示第乙個人的列座標,k表示第二個人的橫座標,l表示第二個人的列座標
3、然後我們就需要列出乙個動態轉移方程,即可以求出走每一步權值的乙個規律方程式,得出方程的思路是:走到這一座標只能是從這個座標的左面或者上面來的,而且每次取每個人中從左面來或者右面來之中的最大值,再從這兩個最大值中取最大的那個,這兩個座標作為路徑的選擇,然後加上兩個人各自座標的權值;所以我們不難推出**:
dp[i]
[j][k]
[l]=
max(
max(dp[i-1]
[j][k-1]
[l],dp[i-1]
[j][k]
[l-1])
,max
(dp[i]
[j-1
][k-1]
[l],dp[i]
[j-1
][k]
[l-1])
)+a[i]
[j]+a[k]
[l];
※但是剛才我們提到了當兩個人走到同一座標的情況:
如果走到了就減去一次當前的權值
if
(i==k && l==j)
//i,j與k,l相同
最後迴圈到(n,n,n,n)時,權值已經加和完畢,可以列印結果了:
cout<[n][n]
[n]<
#include
#include
using
namespace std;
intmain()
for(i=
1;i<=n;i++
)//第乙個人從左或者上來,座標都是從(1,1)開始所以迴圈從1開始}}
}}cout<[n][n]
[n]
}
藍橋網 演算法訓練 方格取數
問題描述 設有n n的方格圖 n 10 我們將其中的某些方格中填入正整數,而其他的方格中則放入數字0。某人從圖的左上角的a 點 1,1 出發,可以向下行走,也可以向右走,直到到達右下角的b點 n,n 在走過的路上,他可以取走方格中的數 取走後的方格中將變為數字0 此人從a點到b 點共走兩次,試找出2...
藍橋杯 方格取數 (多執行緒DP)
演算法訓練 方格取數 時間限制 1.0s 記憶體限制 256.0mb 問題描述 設有n n的方格圖 n 10 我們將其中的某些方格中填入正整數,而其他的方格中則放入數字0。某人從圖的左上角的a 點 1,1 出發,可以向下行走,也可以向右走,直到到達右下角的b點 n,n 在走過的路上,他可以取走方格中...
演算法訓練 方格取數
演算法訓練 方格取數 時間限制 1.0s 記憶體限制 256.0mb 問題描述 設有n n的方格圖 n 10 我們將其中的某些方格中填入正整數,而其他的方格中則放入數字0。某人從圖的左上角的a 點 1,1 出發,可以向下行走,也可以向右走,直到到達右下角的b點 n,n 在走過的路上,他可以取走方格中...