方格取数方格取数 方 格 取 数
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
解题方法:
用四位数组表示两个士兵的位置,详情请见动态转移方程:
动态转移方程:
f[i][j][i1][j1]=max{l+a[i][j](i==i1)and(j==j1)l+a[i][j]+a[i1][j1]elsef[i][j][i1][j1]=max\left\{\begin{matrix}l+a[i][j]&(i==i1)and(j==j1)\\ l+a[i][j]+a[i1][j1]&else\end{matrix}\right. f [ i ] [ j ] [ i 1 ] [ j 1 ] = m a x { l + a [ i ] [ j ] l + a [ i ] [ j ] + a [ i 1 ] [ j 1 ] ( i = = i 1 ) a n d ( j = = j 1 ) e l s e
标注:
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] ; else f[ i] [ j] [ i1] [ j1] = max ( x, y) + a[ i] [ j] + a[ i1] [ j1] ; } printf ( "%d" , f[ n] [ n] [ n] [ n] ) ;
}
提示:
本体的相似题:传纸条(ssl 1589)因太相似就不写了