楼间跳跃----贪心复习

    技术2022-07-11  113

    【题目描述】 在一条街道上有n栋楼,第i栋有hi层,每层都有价值为vi的物品。Lyra可以花费一单位时间在同一栋楼中向上或向下走一层。特别地,每栋楼里都有一个大滑梯,只能从顶楼通往一楼,所以如果Lyra在顶层,可以花费一单位时间通过滑梯到达一楼(注意只有在顶楼才可以使用滑梯)。

    Lyra还可以在不同的楼之间跳跃,即花费一单位时间从当前楼移动到相邻楼的同层,如果相邻楼没有Lyra当前位置高,则会落到相邻楼的顶层。

    初始时Lyra在第一栋楼的顶层,她有m单位时间可以移动,Lyra拿去物品不需要时间,且一个物品被拿一次之后就会消失。Lyra想知道她能获得的总价值最多是多少? 【输入】 第一行两个正整数n,m 以下n行每行两个整数表示hi和vi

    提示:输入数据较大,请采用快速的读入方式。 【输出】

    输出一行一个整数表示最大的总价值。 【输入样例】

    3 3 2 1 1 5 3 4

    【输出样例】

    14

    解题思路:

    核心思想是怎样求最大值,这里是按着第一栋,第1,2栋,第1,2,3栋的顺序, 先是只在第一栋楼里活动,然后判断时间是否超过; 当第2,3栋的时候,如果第二栋的价值比第一栋的大,这就要考虑要不要把第一栋全部换为第二栋(这里考虑换的时候还有两种情况:即是可以全部换,还是只需换一部分); 第1,2,3栋的时候亦是如此。 可以参考下鱼塘钓鱼的题目 没想到第一篇题解竟是这么难的题,qwq #include<bits/stdc++.h> using namespace std; #define ll long long #define val first #define high second priority_queue<pair<ll, ll>, vector<pair<ll, ll>>, greater<pair<ll, ll>>>que; ll n, m; const int M = 1000000; ll h[M + 5], v[M + 5]; int main() { cin >> n >> m; for (int i = 1; i <= n; i++) { cin >> h[i] >> v[i]; h[i]--;//每一楼的第一个是不用花时间的 //即如第一栋有7层,从顶层到底层只需7-1个单位时间 } ll sum = 0; ll ans = 0; ll maxn = 0; for (int k = 1; k <= n; k++) { //按着第一栋,第一栋和第二栋,第1,2,3栋的顺序来 ans += v[k];//在这一栋楼,如第2栋,就直接加上价值,跳到这楼上的时候 if (sum + h[k] <= m) {//此时没有取满,就直接加上 //此时的第二栋的h[i]已经-1,上面加了 sum += h[k];//时间 ans += h[k] * v[k]; que.push(make_pair(v[k], h[k])); }//注意,这里如果没满的话,直接进入到下一层循环,如题目中的 //第二栋只需一次即可。 else {//当此时已经超过时间,就要判断没有加的 //楼和前面已加的楼的方案 pair<ll, ll>a; a = que.top(); while (a.val < v[k] && (!que.empty())) { //如果前一栋楼的数值比现在的小,则把前面一栋的全部换掉(最好) if (sum + h[k] - a.high >= m) {//如果我把前面的 //一栋楼用现在的楼代替还大于m //说明要跟其前前面的楼比较 //把之前的楼删掉 que.pop(); ans = ans - a.high * a.val; sum -= a.high; } else {//如果全部替换后还有多于的时间 //就说明之前的楼只需要丢掉一部分使 //新加的刚好等于m que.pop(); int mid = sum + h[k] - m;//看多出了几层 ans = ans - mid * a.val; //减去多出的层数 a.high -= mid; sum -= mid; que.push(a); break; } a = que.top(); } int mark = m - sum; //求出需要填充几层 pair<ll, ll>q; q.val = v[k]; q.high = mark; if (q.high) { que.push(q); ans = ans + q.val * q.high; sum = m; } } if (ans > maxn) maxn = ans; m--; //每次到下一栋楼就要花费1个单位时间 } cout << maxn; return 0; }

    这题主要运用了贪心算法,虽然不是几个典型的题,但也算是经典,这题也是类似的就只是题解多了点。楼间跳跃这题我好像只找到了2篇,算上我这一篇,我还是借鉴于(https://blog.csdn.net/stldecember/article/details/93976721)。

    最后附上贪心算法的讲解:五大常用算法入门–贪心算法

    Processed: 0.012, SQL: 9