トピック
N×Nグリッドがあります。いくつかの正方形に正の整数を入力し、他の正方形に数値0を入力します。以下に示すように:
誰かが図の左上隅のAから開始し、右下隅のポイントBに到達するまで下または右に歩くことができます。
彼が歩く途中で、彼は正方形の数字を取ることができます(それを取った後の正方形は数字0になります)。
この人は、ポイントAからポイントBまで2回歩いています。得られた数の合計が最大になるように、そのようなパスを2つ見つけてください。
入力形式
最初の行は整数Nで、N×Nグリッドグラフを表します。
後続の各行には3つの整数があり、1つ目は行番号、2つ目は列番号、3つ目は行と列に配置された番号です。
行番号と列番号は1から始まります。
「000」の行は終了を意味します。
出力形式
2つのパスで取得された最大の合計を表す整数を出力します。
データ範囲
N≤10
入力例:
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
出力例:
67
アイデア
一度だけ行く:)
f[i,j]
から(1,1
歩いたすべて(i,j)
のパスの最大値がf[i,j]= max(f[i-1,j]+ w[i], f[i-1][j]+ w[i])
2回行くことを意味します:
f[i1,j1,i2,j2
](1,1),(1,1)
それぞれから歩いたすべて(i1,j1),(i2,j2)
のパスの最大値を意味します。
「同じグリッドを繰り返し選択できない」の対処方法は? 2つの場合
のみi1 + j1 == i2 +j2
パスのグリッドが重なる可能性
f[k, i1, i2]
があります。これは、(1,1),(1,1)
別々に移動したすべて(i1,k-i1), (i2,k-i2)
のパスの最大値と
k
、2つのルートが現在あるグリッドの水平座標と垂直座標の合計を意味します。行きます。
k = i1 + j1 = i2+ j2
したがって、状態遷移に相当f[i1][j1][i2][j2]
する3次元への最適化f[k][i1][i2]
の[i1][k−i1][i2]k−i2]
状態方程式を解く:
4種類の動きを考えます。
記事1:次の記事2:次
f[i1-1]][j1][i2-1][j2]==f[k-1][i1-1][i2-1]
;
第1条:第2条の下で右
f[i1-1][j1][i2][j2-1]==f[k-1][i1-1][i2]
;
記事1:右記事2:ダウン
f[i1][j1-1][i2-1][j2]==f[k-1][i1][i2-1]
;
記事1:正しい記事2:正しい
f[i1][j1-1][i2][j2-1]==f[k-1][i1][i2]
;
コード
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const int N=15;
int w[N][N];
int f[N*2][N][N];
int main()
{
int n;
cin>>n;
int a,b,c;
while(cin>>a>>b>>c,a||b||c) w[a][b]=c;
for(int k=2;k<=n*2;k++)
for(int i1=1;i1<=n;i1++)
for(int i2=1;i2<=n;i2++)
{
int j1=k-i1,j2=k-i2;
int t=w[i1][j1];
if(i1!=i2) t+=w[i2][j2]; //未走到同一格子
if(i1>=1&&i1<=n&&i2>=1&&i2<=n) //判断是否在边界内
{
int &x=f[k][i1][i2];
x=max(x,f[k-1][i1-1][i2-1]+t);
x=max(x,f[k-1][i1-1][i2]+t);
x=max(x,f[k-1][i1][i2-1]+t);
x=max(x,f[k-1][i1][i2]+t);
}
}
cout<<f[n*2][n][n]<<endl;
return 0;
}