思路
首先,这题其实就是找到从到最大和次大的和,但是走过的格子可以重复走,但走过就要把这个格子的价值变成即可,可以考虑四维的状态转移方程,但是再想一下就会发现我们考虑的所有状态都是在的情况下,因此横纵坐标的和相等,故我们考虑,表示当横纵坐标之和,和分别表示两次路径经过点的横坐标,然后纵坐标,可以用和来表示,然后我们考虑状态转移,可以分为四部分,两条路径的点分别从前一个点转移过来,可以分为下下,下右,右下,右右这四种情况,即当前点石油前一个点经过以上操作得来的,点前的两个点左边为,那么前一个点的状态对应分别为,,,,然后如果说明经过了同一个的点,那么我们就只能,否则我们可以
代码
#include <bits/stdc++.h>
using namespace std;
const int N=11;
int dp[N*2][N][N],n,w[N][N],a,b,c;
int main(){
cin>>n;
while(cin>>a>>b>>c){
if(a==0 && b==0 && c==0) break;
w[a][b]=c;
}
for(int k=2;k<=n*2;k++){//k一定要从2开始,因为(1,1)横纵坐标之和为2
for(int i1=1;i1<=n;i1++){
for(int i2=1;i2<=n;i2++){
int j1=k-i1,j2=k-i2;
if(j1<1 || j1>n || j2<1 || j2>n) continue;//保证j1和j2在[1,n]之间
int t=w[i1][j1];
if(j1!=j2) t+=w[i2][j2];//判断是否重合
dp[k][i1][i2]=max(dp[k][i1][i2],dp[k-1][i1-1][i2-1]+t);//下下
dp[k][i1][i2]=max(dp[k][i1][i2],dp[k-1][i1][i2-1]+t);//右下
dp[k][i1][i2]=max(dp[k][i1][i2],dp[k-1][i1-1][i2]+t);//下右
dp[k][i1][i2]=max(dp[k][i1][i2],dp[k-1][i1][i2]+t);//右右
}
}
}
cout<<dp[2*n][n][n];//最后横纵坐标加和=2*n,且都到(n,n)点的最大值。
return 0;
}
分析
这题和上一题几乎一模一样,思路也一样,但有几个细节不一样,要注意一下,第一,横纵坐标之和变成了,然后再后面两重循环的时候要注意和要在之间,所以由此求出,,其他都一样。
代码
#include <bits/stdc++.h>
using namespace std;
const int N=55;
int dp[N*2][N][N],w[N][N],n,m;
int main(){
cin>>n>>m;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
cin>>w[i][j];
}
}
for(int k=2;k<=n+m;k++){
for(int i1=max(1,k-m);i1<=min(k-1,n);i1++){
for(int i2=max(1,k-m);i2<=min(k-1,n);i2++){
int j1=k-i1,j2=k-i2;
if(j1<1 || j1>m || j2<1 || j2>m) continue;
int t=w[i1][j1];
if(i1!=i2 || k==2 || k==m+n){
t+=w[i2][j2];
dp[k][i1][i2]=max(dp[k][i1][i2],dp[k-1][i1-1][i2-1]+t);
dp[k][i1][i2]=max(dp[k][i1][i2],dp[k-1][i1-1][i2]+t);
dp[k][i1][i2]=max(dp[k][i1][i2],dp[k-1][i1][i2-1]+t);
dp[k][i1][i2]=max(dp[k][i1][i2],dp[k-1][i1][i2]+t);
}
}
}
}
cout<<dp[n+m][n][n];
return 0;
}
一些过于简单的题就不展示了。