走方格
下文中视
Subtask1: O(n^4) 暴力枚举。
设
由于
所以
Subtask2: O(n^3)
还是考虑枚举权值变为
关键是如何得出不经过该点的最大得分?
我们可以先考虑如何得出经过
设
同理易得:
显然经过
由于只能向下或向右走,因此我们可以发现不经过
于是将
答案取其最小值即可。
Subtask3: O(n^2)
方法一:
发现
设
可得
Code:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<map>
using namespace std;
#define G() Cr = getchar()
#define LL long long
int Xr, Fr; char Cr;
inline int rd() {
Xr = 0, Fr = 1, G();
while(Cr < '0' || Cr > '9') {if(Cr == '-') Fr = -1; G();}
while(Cr >= '0' && Cr <= '9') Xr = (Xr<<1) + (Xr<<3) + (Cr&15), G();
return Xr * Fr;
}
#define MAX_N 2005
int n, m;
LL va[MAX_N][MAX_N], f[MAX_N][MAX_N], g[MAX_N][MAX_N], F[MAX_N][MAX_N][2], ans = 1e18; // F[i][j][0] -> left
int main() {
n = rd(), m = rd();
for( int i = 1; i <= n; i++)
for( int j = 1; j <= m; j++)
va[i][j] = rd();
for( int i = 1; i <= n; i++ )
for( int j = 1; j <= m; j++ )
f[i][j] = va[i][j] + max(f[i-1][j],f[i][j-1]);
for( int i = n; i >= 1; i-- )
for( int j = m; j >= 1; j-- )
g[i][j] = va[i][j] + max(g[i+1][j],g[i][j+1]);
for( int i = 1; i <= n; i++ )
for( int j = 1; j <= m; j++ )
F[i][j][0] = max( F[i][j-1][0], f[i][j] + g[i+1][j]),
F[i][j][1] = max( F[i-1][j][1], f[i][j] + g[i][j+1]),
ans = min(ans, max( max( F[i][j-1][0], F[i-1][j][1]), f[i][j] + g[i][j] - 2 * va[i][j] ) );
cout << ans;
}
方法二:
这次考虑走的步数,预处理出走
最大得分显然都是
Code:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<map>
using namespace std;
#define G() Cr = getchar()
#define LL long long
int Xr, Fr; char Cr;
inline int rd() {
Xr = 0, Fr = 1, G();
while(Cr < '0' || Cr > '9') {if(Cr == '-') Fr = -1; G();}
while(Cr >= '0' && Cr <= '9') Xr = (Xr<<1) + (Xr<<3) + (Cr&15), G();
return Xr * Fr;
}
#define MAX_N 2005
int n, m;
LL va[MAX_N][MAX_N], f[MAX_N][MAX_N], g[MAX_N][MAX_N], F[MAX_N][MAX_N], G[4005][2], Gx[4005], ans = 1e18; // G[i][0] max G[i][1] 2th_max
int main() {
n = rd(), m = rd();
for( int i = 1; i <= n; i++)
for( int j = 1; j <= m; j++)
va[i][j] = rd();
for( int i = 1; i <= n; i++ )
for( int j = 1; j <= m; j++ )
f[i][j] = va[i][j] + max(f[i-1][j],f[i][j-1]);
for( int i = n; i >= 1; i-- )
for( int j = m; j >= 1; j-- )
g[i][j] = va[i][j] + max(g[i+1][j],g[i][j+1]);
for( int i = 2; i <= n + m; i++ )
for( int k = max(1,i-m); k < min(i,n+1) ; k++ )
if( f[k][i-k] + g[k][i-k] - va[k][i-k] > G[i][0] ) G[i][1] = G[i][0], G[i][0] = f[k][i-k] + g[k][i-k] - va[k][i-k], Gx[i] = k;
else if( f[k][i-k] + g[k][i-k] - va[k][i-k] > G[i][1] ) G[i][1] = f[k][i-k] + g[k][i-k] - va[k][i-k];
for( int i = 1; i <= n; i++ )
for( int j = 1; j <= m; j++ ) {
if( Gx[i+j] == i ) F[i][j] = max(G[i+j][0] - va[i][j], G[i+j][1] );
else F[i][j] = G[i+j][0];
ans = min(F[i][j],ans);
}
cout << ans;
}