P1004 [NOIP2000 提高组] 方格取数 题解(四维dp)
题目链接
题目大意
给你一个n*n的方格图(n<=9),每个格子有权值
某人从图的左上角的 A 点出发,可以向下行走,也可以向右走,直到到达右下角的 B 点。在走过的路上,他可以取走方格中的数(取走后的方格中将变为数字 0)。
此人从 A 点到 B 点共走两次,试找出 2 条这样的路径,使得取得的数之和为最大。
题目思路
如果只走一次很好,直接二维dp
而走两次则可以想象为四维dp,用\(f[i][j][k][l]\)表示第一个人走到(i,j),第二个人走到(k,l)的最优解
注意(i,j)和(k,l)相同特判即可
代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=10+5,mod=1e9+7;
int dp[maxn][maxn][maxn][maxn];
int a[maxn][maxn];
int n;
int main(){
scanf("%d",&n);
while(1){
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
if(u+v+w==0) break;
a[u][v]=w;
}
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
for(int k=1;k<=n;k++){
for(int l=1;l<=n;l++){
dp[i][j][k][l]=max({dp[i-1][j][k-1][l],dp[i-1][j][k][l-1],dp[i][j-1][k-1][l],dp[i][j-1][k][l-1]});
if(i==k&&j==l){
dp[i][j][k][l]+=a[i][j];
}else{
dp[i][j][k][l]+=a[i][j]+a[k][l];
}
}
}
}
}
printf("%d\n",dp[n][n][n][n]);
return 0;
}
还有一个相似的题目
题目链接
代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=50+5,mod=1e9+7,inf=0x3f3f3f3f;
int n,m;
int a[maxn][maxn];
int dp[maxn][maxn][maxn][maxn];
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
scanf("%d",&a[i][j]);
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
for(int k=1;k<=n;k++){
for(int l=1;l<=m;l++){
if(i==k&&j==l&&(!(i==n&&j==m))){
dp[i][j][k][l]=-inf;
}else{
dp[i][j][k][l]=max({dp[i-1][j][k-1][l],dp[i][j-1][k-1][l],dp[i-1][j][k][l-1],dp[i][j-1][k][l-1]})+a[i][j]+a[k][l];
}
}
}
}
}
printf("%d\n",dp[n][m][n][m]);
return 0;
}
不摆烂了,写题