只能算是做题过程记录了,以后想通了再写吧。
看数据量不大还以为过河卒那题写的递归终于能用上了,跑完发现一个数只能用一次,直接递归结果是最大值的双倍,毕竟二维数组两格之间至少有两条路。没想出来【P1004 [NOIP2000 提高组] 方格取数】怎么记录走过的路,想过先求出一个最大,再跑一遍把符合最大值路上的数抹掉,然后再跑一遍找第二大,不过总归没想清楚,而且有点麻烦,再琢磨琢磨吧。
二维数组没想出来好方法,看了看题解,B站搜了搜,基本都用了四维数组,从上左两个来向之间找最大值,并且两次寻路同时进行。题解都是些大佬,总是高估我的理解能力,主要参考了B站这个视频。【P1004 [NOIP2000 提高组] 方格取数】不过这个视频我理解着也挺费劲,本来看这题通过率挺高的,上当了,对我来说要比过河卒复杂的多。
四维数组我理解不动,毕竟还是三维生物,没见过,想不出来。逻辑上是要模拟两次同时走,对比一格走两遍的四种情况,两个都从上走,都从左走,一上一左,一左一上。每一格处理的结果都是继承上一格处理出的最大值,将路径上的最大值与当前格的值相加,就是当前格的值,四维数组里存的,我的理解是对目前走过路径上的最大值的和,只要保证不取同一格的值,最后一格的值就是最大值之和。很难理解,得自己对着题解对着视频,然后开始猛猛参悟,之后就会觉得自己懂了点什么,又好像什么也没懂,但这不要紧,等你觉得有所悟的时候,悟不悟已经不重要了,答案的代码你基本已经记下来了,接下来直接开始化用(程序员的事,怎么能叫抄呢),就解出来啦!
放代码,我自己还得再参悟参悟,等我成为四维生物的时候,应该就能悟透了吧?(假的)
#include <bits/stdc++.h>
using namespace std;
int main(){
int x,y,z,n;
int a[10][10],b[10][10][10][10]={0};
int i,j,k,l;
cin>>n;
for(l=0;l<n*n;l++){
cin>>x>>y>>z;
if(x||y||z){
a[x][y]=z;
}
else{break;}
}
for(i=1;i<=n;i++){
for(j=1;j<=n;j++){
for(k=1;k<=n;k++){
for(l=1;l<=n;l++){
b[i][j][k][l]=max(max(b[i-1][j][k-1][l],b[i-1][j][k][l-1]),
max(b[i][j-1][k-1][l],b[i][j-1][k][l-1]))+a[i][j]+a[k][l];
if(i==k&&j==l){
b[i][j][k][l]-=a[i][j];
}
}
}
}
}
cout<<b[n][n][n][n];
}