[JZOJ5976] [12.15]清華2019冬のキャンプシミュレーション戦闘モンスター(決定単調DP)

説明

ここに画像を挿入説明

入力

ここに画像を挿入説明

出力

ここに画像を挿入説明

サンプル入力

4
3 1 0 2

サンプル出力

5
4
3
1

データ制約

ここに画像を挿入説明

思考

あなたが初めに悪いと一緒に重ね合わせてはいけない、鎧をオーバーレイしたい場合はまだ、再びアーマーアーマー0:00重畳なります。
したがって、我々は短いDPを設定することができ、提供F [i] [j]が位置し、無電力値に滞在する電流iを示し、合計の電流値は、J装甲消費
。1. 1-I〜損傷と集計されている最小傷害とは、明らかにFがある[I] [J] + C [i]の[P]→F [I + P] [J + P] とF [i]は[J] + [I]→F [I + +1] [J]、C
[i]は[P]私は鎧I〜I + P-1、及び損傷、明らかにC [i]と[P] =においてPの重ね合わせを表し 、C [I + 1] [P-1] + MAX([I] -p、0)は、 これ
はO(n ^ 3)を行うことができます。
ここで、この第一のDPを最適化する方法を検討し、移行が観察された発現は、各時刻Fを見出すことができるである[I] [J] Fに転送される[I + P] [J + P] への状態移行
の大きさと第2の大き差は変化せず、その後、C [IP] [P + J]> C = [I]見出すことができる性質を観察Jパケットの状態のIJによれば、
二次転写のその後の除去、に転送します同じグループのために、我々は伝達係数を見て、今のFを考える[I + D] [I ] とF [J + D] [J ]
Fの[D + z]は[Z ] の転送(I > j)が良好である、F参照[I + D] [I ] Fにシフトする[I + D] [I ] + C [I + D] [ZI]→[D + Z] F [ Z]および
F [J + D] [J ] + C [J + D] [ZJ]→F [D + Z] [z]は、 zの増加として見ることができる、C [J + D] [ ZJ ] -c [I +値d] [ZI]を徐々に、単純な用語で、低減され
ていること、比較的小さなZは、F [I + D] [I ] より好ましくから転送、大きなZのためのfで[J + D] [J ] より良いから転送され、我々はできます
スタックモノトーンを更新する、最適な決定間隔を維持するために単調スタックを維持するために、単調決定は、バイナリポイントを必要とし、したがって、複雑性はO(2 ^ N-ある
ログN-)

コード

#include <bits/stdc++.h>

#define F(i, a, b) for (int i = a; i <= b; i ++)
#define G(i, a, b) for (int i = a; i >= b; i --)
#define mem(a, b) memset(a, b, sizeof a)
#define mn(a, b) ((a) = min(a, b))

const int N = 4010;

using namespace std;

int n, TOT, sum, v, ans, G[N][N];
int a[2 * N], ct[N], C[N][N], Len[N], g[N][N], f[2 * N][N];

int main() {
	freopen("griffin.in", "r", stdin);
	freopen("griffin.out", "w", stdout);

	scanf("%d", &n), Len[0] = 1, g[0][1] = 1e9;
	F(i, 1, n) scanf("%d", &a[i]), Len[i] = 1, g[i][1] = 1e9;

	F(i, 1, n) {
		mem(ct, 0);
		F(j, i, n)
			if (a[j] + j - i <= n) ct[a[j] + j - i] ++;
		C[i][0] = a[i], TOT = - ct[0], sum = 0;
		F(j, 1, n) {
			if (i + j - 1 <= n)	TOT ++, sum += a[i + j - 1];
			sum -= TOT, TOT -= ct[j], C[i][j] = sum;
		}
	}

	mem(f, 7), f[0][0] = 0;
	F(i, 0, n - 1) {
		F(d, 0, 2 * n - i - 1)
			mn(f[i + (d + 1)][i], f[i + d][i] + a[i + d + 1]);
		if (i > 0) {
			F(d, 0, n - i - 1) {
				v = G[d][Len[d]];
				if (f[i + d][i] >= f[v + d][v]) continue;
				ans = i;
				for (int l = i + 1, r = n; l <= r; ) {
					int m = l + r >> 1;
					if (f[i + d][i] + C[i + d + 1][m - i] < f[v + d][v] + C[v + d + 1][m - v])
						ans = m, l = m + 1;
					else
						r = m - 1;
				}
				G[d][++ Len[d]] = i, g[d][Len[d]] = ans;
			}
		}
		F(d, 0, 2 * n - i - 1) {
			while (d < n && i + 1 > g[d][Len[d]]) Len[d] --;
			v = d >= n ? 0 : G[d][Len[d]];
			mn(f[(i + 1) + d][i + 1], f[v + d][v] + (v + d + 1 > n ? 0 : C[v + d + 1][i + 1 - v]));
		}
	}

	F(i, 1, n) {
		ans = 1e15;
		F(k, n, n + n - 1) 
			ans = min(ans, f[k][i]);
		printf("%d\n", ans);
	}
}
703元記事公開 ウォンの賞賛392 ビューに14万+を

おすすめ

転載: blog.csdn.net/Eric1561759334/article/details/100724717