動態規劃(3)格子取數問題
阿新 • • 發佈:2018-12-24
問題描述:
有n*n個格子,每個格子裡有正數或者0,從最左上角往右下角走。一共走2次,(即從左上角走到右下角走兩次),把所有經過的格子裡的數加起來,求總和的最大值。如果兩次經過同一個格子,則最後求得的總和中該格子中的數只加一次。
思路:
避免“不顧全域性,只看區域性”(貌似叫貪心)
動態規劃保證全域性最優。
程式碼如下:
const int N = 202;
const int inf = 1000000000;//無窮大
int dp[N*N][N][N];
bool IsValid(int step,int x1,int x2,int n)
{
int y1 = step - x1,y2 = step - x2;
return ((x1 >= 0) && (x1 < n) && (x2 >=0) &&(x2 < n) && (y1 >= 0) && (y1 < n) && (y2 >= 0) && (y2 < n));
}
int GetValue(int step,int x1,int x2,int n)
{
return IsValid(step,x1,x2,n) ? dp[step][x1][x2]:(-inf);
}
//狀態表示dp[step][i][j],並且i <= j
//在第step步,兩人分別在第i行和第j行的最大部分,時間複雜度是O(n^3),空間複雜度為O(n^3)
int MaxPathSum(int a[N][N],int n)
{
int P = n*2-2;
int i,j,step;
for (i = 0;i < n;i++)
{
for (j = i;j < n;j++)
dp[0][i][j] = -inf;
}
}
dp[0][0][0] = a[0][0];
for (step = 1;step <= P;i++)
{
for (i = 0;i < n;i++)
{
for (j = i;j < n;j++)
{
dp[step][i][j] = -inf;
if (!IsValid(step,i,j,n))//非法位置
{
continue;
}
//對於合法的位置進行深度優先搜尋
if (i != j)
{
dp[step][i][j] = max(dp[step][i][j],GetValue(step-1,i-1,j-1,n));
dp[step][i][j] = max(dp[step][i][j],GetValue(step-1,i-1,j,n));
dp[step][i][j] = max(dp[step][i][j],GetValue(step-1,i.j-1,n));
dp[step][i][j] = max(dp[step][i][j],GetValue(step-1,i,j,n));
}
else
{
dp[step][i][j] = max(dp[step][i][j],GetValue(step-1,i-1,j-1,n));
dp[step][i][j] = max(dp[step][i][j],GetValue(step-1,i-1,j,n));
dp[step][i][j] = max(dp[step][i][j],GetValue(step-1,i,j,n));
dp[step][i][j] += a[i][step-i];
}
}
}
return dp[P][n-1][n-1];
}