思路:这道题和摘花生一样,从 左上到右下,每次只能往左走或者往右走,不同的是,从左上到右下要走两次,且每次走过,方格数就变为0,所以要特判是否走到了同一个点;
本题的思路是有两个人一起走,
朴素思路是:
f[i1][j1][i2][j2] //表示从(1,1),(1,1)走到[i1][j1],[i2][j2]最大的值
//状态转移方程:
f[i1][j1][i2][j2]=max(f[i1-1][j1][i2-1][j2]+t,f[i1-1][j1][i2][j2-1]+t,f[i1][j1-1][i2-1][j2]+t,f[i1][j1-1][i2][j2-1]+t)
//t表示两个人走的两格加的权值
//如果相同加一个权值
#include<iostream>
using namespace std;
const int N = 15;
int w[N][N];
int g[N][N][N][N];
int main()
{
int n;
cin>>n;
int a,b,c;
while(cin>>a>>b>>c,a!=0&&b!=0&&c!=0)
{
w[a][b]=c;
}
for(int i1=1;i1<=n;i1++)
{
for(int j1=1;j1<=n;j1++)
{
for(int i2=1;i2<=n;i2++)
{
for(int j2=1;j2<=n;j2++)
{
int t=w[i1][j1];
if(i1!=i2||j1!=j2) t+=w[i2][j2];
int &v=g[i1][j1][i2][j2];
v=max(v,g[i1-1][j1][i2-1][j2]+t);
v=max(v,g[i1][j1-1][i2][j2-1]+t);
v=max(v,g[i1-1][j1][i2][j2-1]+t);
v=max(v,g[i1][j1-1][i2-1][j2]+t);
}
}
}
}
cout<<g[n][n][n][n]<<endl;
return 0;
}
根据上述内容,我们可以发现只有当 i1+j1 == i2+j2 时两者才可能走到同一个格子
这时我们可以优化掉一个纬度,用k表示 i1+j1 和 i2+j2 ,这时只需要枚举k,i1,i2三个常数
#include<iostream>
using namespace std;
const int N = 12;
int f[N*2][N][N];
int w[N][N];
int main()
{
int n;
cin>>n;
int a,b,c;
while(cin>>a>>b>>c,a!=0||b!=0||c!=0) w[a][b]=c;
for(int k=2;k<=n+n;k++)
{
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)//注意边界
{
int t=w[i1][j1];
if(i1!=i2) t+=w[i2][j2];
int &v=f[k][i1][i2];
v=max(v,f[k-1][i1-1][i2-1]+t);//k-1表示上一个状态,
v=max(v,f[k-1][i1][i2-1]+t);//在k状态下,可以有k-1
v=max(v,f[k-1][i1-1][i2]+t);//的两步全部向下或者向右
v=max(v,f[k-1][i1][i2]+t);//或者一个向右一个向下
}
}
}
}
cout<<f[n+n][n][n]<<endl;
return 0;
}
这道题和上一题思路基本一样,
本题是不能走相同的点,而上一题是走到相同的点时,只加一次权值
我们可以证明,上一题的最优的两条路线是可以不重合,因为
当c点为两条最优路线的交点时,Wa和Wb肯定是0,否则绝对会有一条路线通过他们,因为如果相交走的话,c点的权值只会加一次,所以Wa和Wb肯定是0。
那么我们就可以把两天路线的改变一下,并且最终的最大值不变,而且两条路现还不相交。那么就可以用当前这个思路来做本题。
#include<iostream>
using namespace std;
const int N = 60;
int w[N][N];
int f[N*2][N][N];
int main()
{
int n,m;
cin>>n>>m;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
scanf("%d",&w[i][j]);
for(int k=2;k<=n+m;k++)
{
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<=m&&j2>=1&&j2<=m)
{
int t=w[i1][j1];
if(i1!=i2) t+=w[i2][j2];
int &v=f[k][i1][i2];
v=max(v,f[k-1][i1-1][i2-1]+t);
v=max(v,f[k-1][i1-1][i2]+t);
v=max(v,f[k-1][i1][i2-1]+t);
v=max(v,f[k-1][i1][i2]+t);
}
}
}
}
cout<<f[n+m][n][n]<<endl;
return 0;
}