题解/算法 {G - AtCoder Tour}
@LINK: https://atcoder.jp/contests/abc358/tasks/abc358_g
;
答案路径一定形如: S...TTT...T
即到达T后 之后就之前待在原地;
首先 这个T 不一定就是最大值 (因为受限于路径长度K); 因此 我们需要枚举这个T元素, 比如我们枚举(i,j)
作为T 那么你可能认为 从起点开始S...T
的这个前缀 他一定是最短路? (于是你想着用最短路算法 来处理出 起点到每个点的最短路小的 最大权值); 其实这是错误的, 比如S 1 T(9)
他是最短路(长度是2) 假设K=3
那么他的答案就是1+9+9
可是对于S 8 8 T(9)
他虽然不是最短路(长度是3) 但是8+8+9 > 1+9+9
;
因此, S...T
这个路径 并不是最短路, 但可以肯定 他一定是简单路径, 因为我们S...T
他的目的就是 为了到达T
(不会走重复点) 只不过为了达到最大权值 这个路径不一定是最短路;
我们采用暴力枚举, DP(i,j,k)
表示长度为i
的 S ... (j,k)
的路径的最大权值;
static long long DP[ 50*50 + 5][ 51][ 51];
FOR_( I, 0, H*W){
if( I == 0){
std::memset( DP[0], -1, sizeof( DP[0]));
DP[ I][ Si][ Sj] = 0;
continue;
}
FOR_( J, 0, H-1){
FOR_( K, 0, W-1){
auto & CURdp = DP[ I][ J][ K];
CURdp = -1;
for( auto const& dir : vector<pair<int,int> >{ {0,0}, {1,0}, {-1,0}, {0,1}, {0,-1}}){
auto dx = J + dir.first, dy = K + dir.second;
if( dx<0 || dx>=H || dy<0 || dy>=W || DP[I-1][dx][dy]==-1){ continue;}
CURdp = std::max( CURdp, DP[I-1][dx][dy] + A[J][K]);
}
}
}
}
long long ANS = 0;
FOR_( I, 0, std::min( KK,H*W)){
FOR_( J, 0, H-1){
FOR_( K, 0, W-1){
auto & curDP = DP[I][J][K];
if( curDP != -1){
ANS = max( ANS, curDP + (KK - I)*Int64_(A[J][K]));
}
}
}
}
cout<< ANS<< "\n";