概述
题目
题意:有n只怪兽,每只怪兽在
k
i
k_i
ki时间点会出现,且生命值为
h
i
h_i
hi。现在我们需要消灭这
n
n
n只怪兽。由于我们每次打气功,都需要从1开始累计,比如上一秒是打的气功是x,那么这一秒可以打x+1,或者选择重新开始,气功为1。如果上一秒没有打气功,则这一秒只能打1。要消灭这
n
n
n只小怪兽,我们总共需要消耗的最小气功是多少。
思路:
先根据每只小怪兽的生命值,计算消灭这只小怪兽,需要从哪里开始打气功
p
o
s
i
pos_i
posi,比如
k
i
=
6
,
h
i
=
3
k_i=6,h_i=3
ki=6,hi=3,说明我们需要在时间点6-3+1=4的位置开始打气功。如果要批量处理连续区间内的小怪兽,我们需要计算区间
[
l
,
r
]
[l,r]
[l,r]的最小打气功的开始位置
p
p
p,然后计算从
p
p
p到
k
r
k_r
kr的气功总和即可。
由于本题的n比较小,可以支持 n 2 n^2 n2的复杂度。我们可以用dp。令 d p i dp_i dpi表示从i位置结束需要的最小气功。那么 d p i = d p j − 1 + d e a l ( j , i ) , ( 0 < j < = i ) dp_i = dp_{j-1} + deal(j,i),(0<j<=i) dpi=dpj−1+deal(j,i),(0<j<=i)。
计算区间最小值,可以用rmq算法。
注意,如果当前区间
[
j
,
i
]
[j,i]
[j,i]的最小开始下标
p
p
p,小于上一个区间的结束下标位置
k
j
−
1
k_{j-1}
kj−1,则说明区间
[
j
,
i
]
[j,i]
[j,i]的打气功位置和前面的区间发生了交叉,这是不可取的。
#include<bits/stdc++.h>
using namespace std;
const int maxn = 110;
#define ll long long
int n;
ll dp[maxn];
int h[maxn], k[maxn];
int pos[maxn];// 下标i需要的开始位置pos[i]
ll cal(ll x) {
return x * (x + 1) / 2;
}
// rmq求pos数组区间 最小值
int f[maxn][22];
void init_rmq() {
for (int i = 0; i < n; ++i) {
f[i][0] = pos[i];
}
for (int j = 1; (1<<j) <= n; ++j) {
for (int i = 0; i + (1<<j) - 1 < n; ++i) {
f[i][j] = min(f[i][j-1], f[i+(1<<j-1)][j-1]);
}
}
}
int rmq(int l, int r) {
int x = log2(r - l + 1);
return min(f[l][x], f[r-(1<<x)+1][x]);
}
void solve() {
scanf("%d", &n);
for (int i = 0; i < n; ++i) {
scanf("%d", &k[i]);
}
for (int i = 0; i < n; ++i) {
scanf("%d", &h[i]);
}
for (int i = 0; i < n; ++i) {
pos[i] = k[i] - h[i] + 1;
// printf("%d ", pos[i]);
}
// printf("--n");
init_rmq();
dp[0] = cal(h[0]);
// printf("%d", dp[0]);
for (int i = 1; i < n; ++i) {
int p = k[i] - rmq(0, i) + 1;
dp[i] = cal(p);
for (int j = 1; j <= i; ++j) {
// 起始下标超过了上个区间的结束位置,说明有交叉,不可取
if (rmq(j, i) <= k[j-1]) {
continue;
}
p = k[i] - rmq(j, i) + 1;
dp[i] = min(dp[i], dp[j-1] + cal(p));
}
// printf(" %d ", dp[i]);
}
// printf("---n");
printf("%lldn", dp[n-1]);
}
int main() {
int t;
scanf("%d", &t);
// int cas = 1;
while (t--) {
// printf ("case %dn", cas++);
solve();
}
}
/*
9
3
1 2 4
1 2 3
3
1 2 3
1 1 2
*/
最后
以上就是冷艳哈密瓜为你收集整理的Monsters And Spells(dp/rmq)的全部内容,希望文章能够帮你解决Monsters And Spells(dp/rmq)所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复