三取方格数

描述

设有N*N的方格图,我们将其中的某些方格填入正整数,而其他的方格中放入0。

某人从图得左上角出发,可以向下走,也可以向右走,直到到达右下角。在走过的路上,他取走了方格中的数。(取走后方格中数字变为0)此人从左上角到右下角共走3次,试找出3条路径,使得取得的数总和最大。

格式

输入格式

第一行:N (4<=N<=20)
接下来一个N*N的矩阵,矩阵中每个元素不超过80,不小于0

输出格式

一行,表示最大的总和。

样例1

样例输入1[复制]

 
4
1 2 3 4
2 1 3 4
1 2 3 4
1 3 2 4

样例输出1[复制]

 
39

限制

各个测试点1s

提示

多进程DP

  f[step][x1][x2][x3]表示当走到第step步时,三个点分别取x1,x2,x3时的最优解。

  由于只能向下或向右移动,所以当移动步数一定时,所能移动到的格子是一个 / 的对角线,所以枚举三次移动到的横坐标,可以O(1)第算出纵坐标,注意每个方格只能取一次。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstdlib>
 4 #include<cstring>
 5 #include<cmath>
 6 #include<algorithm>
 7 using namespace std;
 8 const int maxn=25;
 9 int f[maxn*2][maxn][maxn][maxn];
10 int map[maxn][maxn];
11 int N;
12 int main(){
13     
14     scanf("%d",&N);
15     for(int i=1;i<=N;i++){
16         for(int j=1;j<=N;j++){
17             scanf("%d",&map[i][j]);
18         }
19     }
20     f[1][1][1][1]=map[1][1];
21     for(int step=2;step<=2*N-1;step++){//枚举步数,假定走到 (1,1) 用了一步 
22         for(int x1=max(1,step-N+1);x1<=min(N,step);x1++){//x1,x2,x3 是用 step步走到横坐标为 x1,x2,x3的方格,
23             for(int x2=max(1,step-N+1);x2<=min(N,step);x2++){//用min(),max()都是保证方格不越界的方式 
24                 for(int x3=max(1,step-N+1);x3<=min(N,step);x3++){
25                     int delta=map[x1][step-x1+1]+map[x2][step-x2+1]+map[x3][step-x3+1];
26                     if(x1==x2) delta-=map[x1][step-x1+1];
27                     if(x1==x3) delta-=map[x1][step-x1+1];
28                     if(x2==x3) delta-=map[x2][step-x2+1];
29                     if(x1==x2&&x1==x3) delta+=map[x1][step-x1+1];//多减去了一次 
30                     
31                     f[step][x1][x2][x3]=max(f[step-1][x1][x2][x3],max(f[step-1][x1-1][x2][x3],
32                                         max(f[step-1][x1][x2-1][x3],max(f[step-1][x1][x2][x3-1],
33                                         max(f[step-1][x1-1][x2-1][x3],max(f[step-1][x1-1][x2][x3-1],
34                                         max(f[step-1][x1][x2-1][x3-1],f[step-1][x1-1][x2-1][x3-1])))))))+delta;
35                     
36                     
37                 }
38             }
39         }
40     }
41     cout<<f[2*N-1][N][N][N];
42     return 0;
43 }

 

posted @ 2015-09-06 19:14  CXCXCXC  阅读(829)  评论(0编辑  收藏  举报