# 洛谷P8096 「USACO 2022.1 Gold」Drought

## 本题题解

$\mathrm{dp}(i, j) = \sum_{h_i = j}^{H_i} \mathrm{dp}(i - 1, h_i - j)$

$$n$$ 是偶数，最终答案就是 $$\mathrm{dp}(n, 0)$$。若 $$n$$ 是奇数，定义状态时要加上一个条件：当 $$i$$ 是奇数时 $$j\geq k$$。最终答案是所有 $$k$$ 对应的 $$\mathrm{dp}(n, k)$$ 之和。

## 参考代码

// problem: P8096
#include <bits/stdc++.h>
using namespace std;

#define mk make_pair
#define fi first
#define se second
#define SZ(x) ((int)(x).size())

typedef unsigned int uint;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;

template<typename T> inline void ckmax(T& x, T y) { x = (y > x ? y : x); }
template<typename T> inline void ckmin(T& x, T y) { x = (y < x ? y : x); }

const int MAXN = 100, MAXH = 1000;
const int MOD = 1e9 + 7;
int n, H[MAXN + 5], dp[MAXN + 5][MAXH + 5], sum[MAXH + 5];

int main() {
cin >> n;
for (int i = 1; i <= n; ++i) {
cin >> H[i];
}

if (n % 2 == 0) {
// n 是偶数
dp[0][0] = 1;
for (int i = 1; i <= n; ++i) {
for (int j = 0; j <= H[i]; ++j) { // d[i]
for (int h = j; h <= H[i]; ++h) { // d[i] = h - d[i - 1]
dp[i][j] = (dp[i][j] + dp[i - 1][h - j]) % MOD;
}
}
}
cout << dp[n][0] << endl;
} else {
int ans = 0, lim = MAXH;
for (int i = 1; i <= n; i += 2) {
// 对所有奇数位置：k <= d[i] <= h[i] <= H[i]
// 所以 k 的上限是这些 H[i] 的 min
ckmin(lim, H[i]);
}
for (int k = 0; k <= lim; ++k) {
dp[0][0] = 1;
for (int i = 1; i <= n; ++i)
for (int j = 0; j <= MAXH; ++j)
dp[i][j] = 0; // 清空
for (int i = 1; i <= n; ++i) {
sum[0] = dp[i - 1][0];
for (int j = 1; j <= MAXH; ++j) {
sum[j] = (sum[j - 1] + dp[i - 1][j]) % MOD;
}
for (int j = (i % 2 == 0 ? 0 : k); j <= H[i]; ++j) { // d[i]
/*
for (int h = j; h <= H[i]; ++h) { // d[i] = h - d[i - 1]
dp[i][j] = (dp[i][j] + dp[i - 1][h - j]) % MOD;
}
*/
dp[i][j] = sum[H[i] - j];
}
}
ans = (ans + dp[n][k]) % MOD;
}
cout << ans << endl;
}

return 0;
}

posted @ 2022-03-16 22:33  duyiblue  阅读(225)  评论(0编辑  收藏  举报