过题代码
#include <iostream>
#include <queue>
#include <cmath>
using namespace std;
const int N=1e5+10;
//贪心算法
int main() {
priority_queue<int> pq;
int n,q,p;
cin>>n>>p>>q;
for (int i = 1; i <=n; i++) {
int x;
cin>>x;
pq.push(x);
}
while (p||q){
int max=pq.top();
pq.pop();
if(p){
max= sqrt(max);
p--;
} else if(q){
max/=2;
q--;
}
pq.push(max);
}
int s=0;
while (!pq.empty()){
s+=pq.top();
pq.pop();
}
cout<<s<<endl;
return 0;
}
通过贪心算法解决爬山问题,下面是代码的基本思路和解题步骤:
### 代码思路:
1. 使用一个优先队列(最大堆)来存储所有山的高度,这样可以快速获取当前最高的山。
2. 通过两种魔法来降低山的高度,以减少爬山所需的体力值。
3. 重复使用魔法,直到没有剩余的魔法次数。
4. 最后,计算并输出所有山的总高度,这将是爬山所需的最小体力值。
### 解题步骤:
1. **初始化**:定义一个优先队列 `pq` 来存储山的高度,以及两个变量 `p` 和 `q` 来存储两种魔法的使用次数。
2. **输入**:读取山的数量 `n`,以及两种魔法的使用次数 `p` 和 `q`。然后,读取每座山的高度,并将它们加入到优先队列中。
3. **魔法使用**:
- 当还有魔法次数剩余时,执行循环。
- 从优先队列中取出最高的山 `max`。
- 如果第一种魔法次数 `p` 还有剩余,使用第一种魔法将山的高度降低到 `sqrt(max)`,并减少 `p` 的次数。
- 如果第一种魔法次数用尽,但第二种魔法次数 `q` 还有剩余,使用第二种魔法将山的高度降低到 `max/2`,并减少 `q` 的次数。
4. **重新加入队列**:将使用魔法后的新高度重新加入到优先队列中。
5. **计算总体力值**:当所有魔法次数都使用完毕后,清空优先队列,将所有山的高度相加,得到总的体力值。
6. **输出结果**:输出爬山所需的最小体力值。
###代码潜在问题:
循环条件:在 while (p||q)
循环中,如果 p
和 q
同时为0,循环应该停止。但是,如果 p
和 q
都为0,代码中没有检查这个条件,可能会导致无限循环。
###循环代码改善:
if (p > 0) {
max = (int)sqrt(max);
p--;
} else if (q > 0) {
max /= 2;
q--;
}
相比于原来的while,这一段代码改善后能够有效的防止无限循环的问题