优先队列的注意点及题目

题目一 

I-礼物商店_第二届“重科杯”重庆科技大学程序设计竞赛 (nowcoder.com)

题解 

感想:这道题目没有太多技术含量,只需要用一个优先队列每一次维护一个结构体,结构体的成员分别是价格和数量。但是对于初学者的我,有很多可以注意的地方。

结构体含有带参数的构造函数

这道题目我首先在结构体内定义了带有参数的构造函数。现在,应该注意的地方来了:

如果我在结构体内定义了带有参数的构造函数,那么我将不能声明一个结构体的数组。

报错代码

struct Goods {
    int w;
    int cnt;
    // 带参数的构造函数
    Goods(int a, int b) : w(a), cnt(b) {}
};
Goods items[10]; // 编译错误:没有默认构造函数

如果我们试图声明这种结构体或类的数组而没有提供默认构造函数,编译器会因为没有合适的构造函数来初始化数组中的每个元素而报错。

 那么我们应该怎么解决呢?

那我们就可以在结构体同时定义参数构造函数还有默认构造函数

struct Goods {
    int w;
    int cnt;
    // 默认构造函数
    Goods() : w(0), cnt(0) {}
    // 带参数的构造函数
    Goods(int a, int b) : w(a), cnt(b) {}
};

Goods items[10]; // 现在这是有效的,每个元素都会使用默认构造函数初始化

结构体不含有带参数的构造函数

如果结构不含带参数的构造函数,那么就简单一点了,结构体代码如下 

 其中 ll 是 long long

struct Goods{
    ll w;    // 商品价格
    ll cnt;  // 可购买次数
}a[N];

完整AC代码 

#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int N = 1e5+10;

struct Goods{
    ll w;    // 商品价格
    ll cnt;  // 可购买次数
}a[N];

struct Compare{
    bool operator()(Goods a, Goods b){
        return a.w > b.w; // 优先队列,最小的价格在顶部
    }
};

int main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    int n, m, k;
    cin >> n >> m >> k;
    priority_queue<Goods, vector<Goods>, Compare> pq;

    for(int i = 0; i < m; i++) cin >> a[i].cnt;
    for(int i = 0; i < m; i++) {
        cin >> a[i].w;
        pq.push({a[i].w, a[i].cnt});  // 正确推入价格 w 和数量 cnt,这里的顺序不能换哦
    }

    ll ans = 0;
    while(n--) {
        if (pq.empty()) break; // 避免队列为空时继续访问

        Goods temp = pq.top(); pq.pop();
        ans += temp.w;          // 累加价格
        temp.cnt--;             // 减少剩余可购买次数

        if(temp.cnt > 0) {
            temp.w = (temp.w + k) | (temp.w & k); // 更新价格
            pq.push(temp);      // 如果还可以购买,重新入队
        }
    }
    cout << ans << '\n';
    return 0;
}

那么我们可以在某些情况下省略带参数的构造函数,什么时候需要呢?

当我们的结构体对象包含多个成员变量,且这些变量在创建对象时需要立即被初始化为特定值时,带参数的构造函数非常有用。这样可以确保对象在使用前已正确设置其状态。例如,在处理几何问题时,定义点、向量或其他几何结构体并立即赋予坐标值。

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值