【動態規劃】方格取數 (ssl 1010)
阿新 • • 發佈:2018-12-16
Description
設有N*N的方格圖(N<=10,我們將其中的某些方格中填入正整數,而其他的方格中則放入數字0。如下圖所示(見樣例):
某人從圖的左上角的A 點出發,可以向下行走,也可以向右走,直到到達右下角的B點。在走過的路上,他可以取走方格中的數(取走後的方格中將變為數字0)。
此人從A點到B 點共走兩次,試找出2條這樣的路徑,使得取得的數之和為最大。
Input
輸入的第一行為一個整數N(表示N*N的方格圖),接下來的每行有三個整數,前兩個表示位置,第三個數為該位置上所放的數。一行單獨的0表示輸入結束。
Output
只需輸出一個整數,表示2條路徑上取得的最大的和。
Sample Input
8
2 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
Sample Output
67
題目大意:
有兩個士兵,從1,1走到n,n路上有許多money,但他們只能往下或往右走,他們最多能得到多少money
解題方法:
用四位陣列表示兩個士兵的位置,詳情請見動態轉移方程:
動態轉移方程:
標註:
ij分別為第一個士兵的行列,i1j1分別為第二個士兵的行列,l為上一步最大的,第一行是因為重複了,金幣只能拿一份,第二行是兩個士兵那兩份
#include<cstdio>
#include<iostream>
using namespace std;
int n,x,y,d,a[12][12],f[12][12][12][12];
int main()
{
scanf("%d%d%d%d",&n,&x,&y,&d);
while (!((x==0)&&(y==0)&&(d==0)))//判斷結束為
{
a[x][y]=d;//放進圖中
scanf("%d%d%d",&x,&y,&d);
}
for (int i=1;i<=n;i++)//士兵一的行
for (int j=1;j<=n;j++)//士兵一的列
for (int i1=1;i1<=n;i1++)//士兵二的行
for (int j1=1;j1<=n;j1++)//士兵二的列
{
x=max(f[i-1][j][i1-1][j1],f[i][j-1][i1][j1-1]);//分別為上上,左左(這要倒著)
y=max(f[i-1][j][i1][j1-1],f[i][j-1][i1-1][j1]);//分別為上左,左上
if ((i==i1)&&(j==j1)) f[i][j][i1][j1]=max(x,y)+a[i][j];//重複,先把x,y合併,再加當前格子的金幣
else f[i][j][i1][j1]=max(x,y)+a[i][j]+a[i1][j1];//要加兩遍
}
printf("%d",f[n][n][n][n]);//輸出兩位士兵都到n,n時的結果
}