四维dp:状态太多就多开数组。
P1004
题目链接:https://www.luogu.com.cn/problem/P1004
思路:
因为有两条路径,他们之间相互影响,如果走到相同的地点只算一次aij。
状态转移方程:dp(i,j,p,q) = max { dp(i-1,j,p-1,q) , dp(i-1,j,p,q-1) , dp(i,j-1,p-1,q) , dp(i,j-1,p,q-1) } + a[i][j] + a[p][q];
如果i == p && j == q,dp(i,j,p,q) = max { dp(i-1,j,p-1,q) , dp(i-1,j,p,q-1) , dp(i,j-1,p-1,q) , dp(i,j-1,p,q-1) } + a[i][j] ;
代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll a[12][12] = {0},dp[12][12][12][12] = {0};
ll Max(ll x,ll y,ll z,ll d)
{
return max(max(x,y),max(z,d));
}
int main(void)
{
int n,x,y,z;
scanf("%d",&n);
while(~scanf("%d%d%d",&x,&y,&z))
{
if(x == 0 && y == 0 && z == 0) break;
a[x][y] = z;
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
for(int p=1;p<=n;p++)
{
for(int q=1;q<=n;q++)
{
if(i == p && j == q)
{
dp[i][j][p][q] = Max(dp[i-1][j][p-1][q],dp[i-1][j][p][q-1],
dp[i][j-1][p-1][q],dp[i][j-1][p][q-1]) + a[i][j];
}
else{
dp[i][j][p][q] = Max(dp[i-1][j][p-1][q],dp[i-1][j][p][q-1],
dp[i][j-1][p-1][q],dp[i][j-1][p][q-1])
+ a[i][j] + a[p][q];
}
}
}
}
}
printf("%lld\n",dp[n][n][n][n]);
return 0;
}
P1006
题目链接:https://www.luogu.com.cn/problem/P1006
思路:
与上面的题目类似,有两条路径s1->sn,sn->s1,如果第一条路径走过了aij,第二条路径就不能记录aij的值,
其实就是上面那题,把数据变大了。
代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll a[52][52] = {0},dp[52][52][52][52] = {0};
ll Max(ll x,ll y,ll z,ll d)
{
return max(max(x,y),max(z,d));
}
int main(void)
{
int n,m,x,y,z;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++) scanf("%lld",&a[i][j]);
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
for(int p=1;p<=n;p++)
{
for(int q=1;q<=m;q++)
{
if(i == p && j == q)
{
dp[i][j][p][q] = Max(dp[i-1][j][p-1][q],dp[i-1][j][p][q-1],
dp[i][j-1][p-1][q],dp[i][j-1][p][q-1]) + a[i][j];
}
else{
dp[i][j][p][q] = Max(dp[i-1][j][p-1][q],dp[i-1][j][p][q-1],
dp[i][j-1][p-1][q],dp[i][j-1][p][q-1])
+ a[i][j] + a[p][q];
}
}
}
}
}
printf("%lld\n",dp[n][m][n][m]);
return 0;
}