二刷提高课,题解目录在这里— 提高课的题解目录
这里说明一下为什么不能两边走,而是一边走
首先当我们走两边的时候,第一遍我们要求了它不仅要按照要求走还要走局部最优解
这就导致了一种可能,第一遍某一步走右边是全局最优而走下面是局部最优
根据思路我们可知肯定走了下面,这就导致,第二遍走的时候存在一种可能
这个右边我们可能走不了,为什么?
因为我们不保证了不是走下就是走右,若下面更大(比第一遍走的要小)
就导致这个右边的点没有取到,所有必定不是全局最优
为什么走一遍就保证全局最优?
我们走一遍并没有规定每一步必须选哪个,我们只需要在最后的时候最大即可
也就是说我们取消了走第一遍强求最优的这个限制,所以可以达成全局最优
可是当我们两次一起走的时候,若用四层循环并不容易处理走两次的操作
我们可以发现我们每次走不是下就是右,
所以我们每次走的下的步数与右的步数相加一定相等
所以我们其实只需要三次循环就够了使用了i,用k来限制重复以及得出j
#include<iostream>
#include<cstring>
using namespace std;
int f[30][15][15];
int w[15][15];
int n,a,b,c;
int main()
{
cin>>n;
while(cin>>a>>b>>c,a||b||c)
{
w[a][b]+=c;
}
f[2][1][1]=w[1][1];
for(int k=3;k<=n*2;k++)//为什么k放第一循环?因为k固定了而ij的位置其实不固定
{
for(int x1=1;x1<=n;x1++)
{
for(int x2=1;x2<=n;x2++)
{
int y1=k-x1,y2=k-x2;
if(y1<1||y2<1)continue;
int &xx=f[k][x1][x2];
xx=max(xx,f[k-1][x1][x2-1]);
xx=max(xx,f[k-1][x1-1][x2]);
xx=max(xx,f[k-1][x1-1][x2-1]);
xx=max(xx,f[k-1][x1][x2]);//意为均从y转移过来
if(x1==x2)xx+=w[x1][y1];
else xx+=(w[x1][y1]+w[x2][y2]);
}
}
}
cout<<f[2*n][n][n];
return 0;
}