问题描述
设有N*N的方格图(N<=10),我们将其中的某些方格中填入正整数,而其他的方格中则放入数字0。
某人从图的左上角的A 点(1,1)出发,可以向下行走,也可以向右走,直到到达右下角的B点(N,N)。在走过的路上,他可以取走方格中的数(取走后的方格中将变为数字0)。
此人从A点到B 点共走两次,试找出2条这样的路径,使得取得的数之和为最大。
输入格式
输入的第一行为一个整数N(表示N*N的方格图),接下来的每行有三个整数,前两个表示位置,第三个数为该位置上所放的数。一行单独的0表示输入结束。
输出格式
只需输出一个整数,表示2条路径上取得的最大的和。
样例输入
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
设有N*N的方格图(N<=10),我们将其中的某些方格中填入正整数,而其他的方格中则放入数字0。
某人从图的左上角的A 点(1,1)出发,可以向下行走,也可以向右走,直到到达右下角的B点(N,N)。在走过的路上,他可以取走方格中的数(取走后的方格中将变为数字0)。
此人从A点到B 点共走两次,试找出2条这样的路径,使得取得的数之和为最大。
输入格式
输入的第一行为一个整数N(表示N*N的方格图),接下来的每行有三个整数,前两个表示位置,第三个数为该位置上所放的数。一行单独的0表示输入结束。
输出格式
只需输出一个整数,表示2条路径上取得的最大的和。
样例输入
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
思路
一个人走两次可以看做两个人同时走,这里有两个要点:
x1+y1=x2+y2 也就是说这两人并排在一条斜线
为了和最大,两人除了开头结尾,不能走过同一个格子上
蓝桥oj最后一个测试数据貌似有问题;锦囊里的那个递推式不符合最优子结构,因为F(i-1,j,k'')不是最大,但是两个V值足够大,也能得到最优解
#include<stdio.h>
#define max2(a,b) a>b?a:b
#define min2(a,b) a<b?a:b
int a[100][100]={0};//储存表格
int N;
int main(){
int x,y,i,j,k,q,t,max,min,x1,x2;
int dp[20][20][20][20]={0};//储存从两点到终点的路径经过的数值和的最大值
int yb[2],yc[2],xb[2],xc[2];
scanf("%d",&N);
while(1){
scanf("%d%d",&x,&y);
scanf("%d",&a[x][y]);
if(x==0&&y==0&&a[x][y]==0)
break;
}
dp[N][N][N][N]=a[N][N];
for(i=2*N-1;i>=2;i--){//两点总在同一直线上,i=x+y,把表格看作一条一条斜线
max=min2(N,i-1);
min=max2(1,i-N);
for(x1=min;x1<=max;x1++){
for(x2=min;x2<=max;x2++){//遍历在这条斜线上,两个点的任意组合
if(x1==x2&&!(x1==1&&x2==1))continue;
yb[0]=i-x1+1;
yb[1]=i-x1;
xb[0]=x1;
xb[1]=x1+1;
yc[0]=i-x2+1;
yc[1]=i-x2;
xc[0]=x2;
xc[1]=x2+1;
q=0;
for(j=0;j<=1;j++){
for(k=0;k<=1;k++){
if(xb[j]==xc[k])continue;//同一直线,x不同,就不会重叠
if(q<(t=a[x1][i-x1]+a[x2][i-x2]+dp[xb[j]][yb[j]][xc[k]][yc[k]])){
q=t;
}
}
}
dp[x1][i-x1][x2][i-x2]=q;
}
}
}
dp[1][1][1][1]-=a[1][1];
printf("%d",dp[1][1][1][1]);
return 0;
}