题目链接:
https://codeforces.com/problemset/problem/1561/C
题目大意:
t 组测试,有 n 个洞穴,每个洞穴有 k 个怪,每个怪有一个 armor 值,在洞穴中需要按照顺序打怪,你有一个 power 值,当 power 大于 怪的 armor 时,你可以打过这个怪,否则失败,每打一个怪,你的 power + 1,找到一个 最小 的 power 值,让你能够按照一定的顺序成功通过所有洞穴。
思路:
首先要知道 通过某个洞穴的最小 power 。
我们设要打的第一个洞穴的第一个怪的 armor 是 a(1) ,那么进入这个洞穴时的 power 是 a(1) + 1 时才能打过第一个怪,第二个怪的 armor 是 a(2) ,那么进入洞穴时 power 至少要为 a(2) + 1 - 1 时才能打过第二个怪, + 1 满足了 power > armor , - 1 是因为在这之前打了一个怪。我们要取两者中的 较大值 。
显然,我们可以递推得到打过这个洞穴中某个怪的 最小的进入洞穴时的 power 值 (有点绕) ,再取其中的最大值,就得到通过这个洞穴的最小的 power 。
接下来我们要去计算通过所有洞穴的最小的 power 值。
将通过每一个洞穴的最小 power 值(定义为 begin )及通过这个洞穴后增加的值 k 储存在结构体中,然后按照 begin 从小到大进行排序。
ps:我们设可以当前找过的所有洞穴的最小的 power 值为 ans ,通过前面所有洞穴增长的 power 为 len.
显然,会出现两种情况:
一、 ans + len < 当前洞穴的 begin ,那么 ans 的值就要更改为 begin - len。
二、 ans + len >= 当前洞穴的 begin ,那么 ans 不变。
即 ans = max( ans , begin - len );
代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int MAXN = 100005;
struct power{
int b, l;
}p[MAXN];
LL a;
int t, n, k, start, len;
bool cmp (power a,power b){
return a.b < b.b;
}
int main(){
cin >> t;
while (t--){
scanf("%d", &n);
for (int i = 1; i <= n; i++){
scanf("%d", &k);
p[i].l = k;
p[i].b = 0;
for (int j = 1; j <= k; j++){
scanf("%d", &a);
p[i].b = p[i].b > a - j + 2 ? p[i].b : a - j + 2;
}
}
sort(p + 1, p + n + 1, cmp);
start = p[1].b;
len = p[1].l;
for (int i = 2; i <= n; i++){
if (p[i].b > start + len) start = p[i].b - len;
len += p[i].l;
}
cout << start << "\n";
}
return 0;
}```