方格取数 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
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 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Source | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
NOIp2000提高组 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Recommend | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
黄李龙 |
状态转移:(其中 i,j表示第一个人的位置坐标,ii,jj表示第二个人的位置坐标,dp[ i ][ j ][ ii ][ jj ]可表示所以情况,注意当两人走到同一个位置时只有一人能拿到点数)
dp[i][j][ii][jj] = max(dp[i-1][j][ii-1][jj], max(dp[i-1][j][ii][jj-1],
max(dp[i][j-1][ii-1][jj], dp[i][j-1][ii][jj-1]))) + a[i][j] + a[ii][jj];
if(i == ii && j == jj) dp[i][j][ii][jj] -= a[i][j];
完整代码:
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <queue>
#include <algorithm>
using namespace std;
const int N = 1e5 + 10;
int n;
int a[15][15];
int dp[15][15][15][15];
int main(){
while(scanf("%d", &n) == 1){
int u, v, w;
memset(dp, 0, sizeof(dp));
memset(a, 0, sizeof(a));
while(scanf("%d%d%d", &u, &v, &w) == 3){
if(u == 0 && v == 0 && w == 0) break;
a[u][v] = w;
}
for(int i = 1; i <= n; i++){
for(int j = 1; j <= n; j++){
for(int ii = 1; ii <= n; ii++){
for(int jj = 1; jj <= n; jj++){
if(i + j != ii + jj) continue;
dp[i][j][ii][jj] = max(dp[i-1][j][ii-1][jj], max(dp[i-1][j][ii][jj-1],
max(dp[i][j-1][ii-1][jj], dp[i][j-1][ii][jj-1]))) + a[i][j] + a[ii][jj];
if(i == ii && j == jj) dp[i][j][ii][jj] -= a[i][j];
}
}
}
}
printf("%d\n", dp[n][n][n][n]);
}
}
/*
3
1 2 3
2 1 4
2 2 5
0 0 0
4
2 3 3
3 2 4
3 3 5
0 0 0
*/