题解-luogu-cf1195c Basketball Exercise

题目链接

给定一个$2*n$的矩阵,从中选出若干数,且任意两个数不上下或左右相邻,求这些数的最大总和

$1\le n \le 100000,1 \le h_{i,j}\le 1000000000$

很水的一道C题……目测难度在黄~绿左右。请各位切题者合理评分。

注意到可以选择的球员编号是严格递增的,因此可以把状态的第一维定义为球员编号,第二维描述编号同为 $i$ 的两名球员的选取情况。

定义状态:$f[i][0/1/2]$ 表示选取了编号在 $i$ 及以前的球员,所能得到的身高总和最大值。其中,第二维的 $0$ 表示编号为 $i$ 的球员一个都不选;$1$ 表示只选上面一个;$i$ 表示只选下面一个。(显然没有上下都选的情况)

状态转移方程:
$$
f[i][0]=max\lbrace f[i-1][0],f[i-1][1],f[i-1][2]\rbrace
$$
$$
f[i][1]=max\lbrace f[i-1][0],f[i-1][2]\rbrace+height[i][1]
$$
$$
f[i][2]=max\lbrace f[i-1][0],f[i-1][1]\rbrace+height[i][2]
$$

Update: 用贪心可以证明,在最优解中,不会出现连续两列一个不取的情况。因此, $f[i][0]$ 其实没有必要考虑来自 $f[i-1][0]$ 的状态转移。

代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int N;
ll h[100005][3];
ll f[100005][3];
int main() {
cin >> N;
for (register int i = 1; i <= N; ++i) cin >> h[i][1];
for (register int i = 1; i <= N; ++i) cin >> h[i][2];
f[1][0] = 0;
f[1][1] = h[1][1];
f[1][2] = h[1][2];
for (register int i = 2; i <= N; ++i) {
f[i][0] = max(f[i - 1][0], max(f[i - 1][1], f[i - 1][2]));
f[i][1] = max(f[i - 1][0], f[i - 1][2]) + h[i][1];
f[i][2] = max(f[i - 1][0], f[i - 1][1]) + h[i][2];
}
cout << max(f[N][0], max(f[N][1], f[N][2]));
return 0;
}

Comments

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×