# 課堂練習

# f627: 1. 礦砂採集

https://zerojudge.tw/ShowProblem?problemid=f627

這是一個典型的部分背包問題,
每一次取礦石都取當前剩下性價比 (CP 值) 最高的礦石。

運用 pair 分別紀錄初始重量以及單位重量價值 (CP 值)。
再使用自定比較函式,由高到低排序 CP 值。
當背包還有空間時,就不斷的提取。

#include <bits/stdc++.h>
using namespace std;
#define pii pair<int,int>
bool comp(pii a,pii b){
    return a.first>b.first;
}
int main(){
    int n,m,w,p;
    while(cin >> n >> m)
    {
        vector<pii>v;
        for(int i=0;i<n;i++){
            cin >> w >> p;
            v.push_back({p,w});
        }
        sort(v.begin(),v.end(),comp);
        int sum=0;
        for(int i = 0;i<n;i++) {
            if (m>v[i].second) {
                sum +=  v[i].second*v[i].first;
                m -= v[i].second;
            }
            else{
                sum += min(v[i].second,m)*v[i].first;
                break;
            }
        }
        cout << sum << endl;
    }
    return 0;
}

# 延伸練習

# e538: 11389 - The Bus Driver Problem

在一個城市裡,有 n 個巴士司機。有 n 條早晨巴士路線和 n 條傍晚巴士路線。
對於任何駕駛員,如果一天的總路線長度超過 d,則必須在 d 小時後以每小時 r 元支付加班費。
您的任務是為每個巴士司機分配一條早上路線和一條傍晚路線,以使支付的總加班費最小。

每一個巴士司機,配給一條當前剩下最短的早上路線與最長的傍晚路線。
這樣就能使超過 d 的數量最少。

#include <bits/stdc++.h>
using namespace std;
int main()
{
    int n,d,r;
    while(cin>>n>>d>>r &&n&&d&&r){
        int day[n],night[n];
        for(int i = 0;i<n;i++)
            cin>>day[i];
        for(int i = 0;i<n;i++)
            cin>>night[i];
        sort(day,day+n);
        sort(night,night+n,greater<int>());
        int sum = 0;
        for(int i = 0;i<n;i++)
            if(day[i]+night[i]>d)
                    sum+=(day[i]+night[i]-d) *r ;
        cout<<sum<<endl;
    }
    return 0;
}

# f832: 隕石 (Meteorite)

已知 OI 國有 M 個隕石捕捉器,每一個捕捉器只能使用一次,而且只可捕捉一個隕石。
第 i 個捕捉器可以捕捉一個重量不超過CiC_i 單位重的隕石。
N 顆隕石的重量已由科學家估算出來,重量分別為 W1WNW_1 ~ W_N
隕石上稀有物質的含量正比於該隕石的重量,目標是要最大化捕捉隕石的重量總和。

每一個捕捉器都只取小於自己的最大隕石即可。

#include <bits/stdc++.h>
using namespace std;
#define int long long
bool high(int a,int b){
    return a>b;
}
signed main(){
    int n,m;
    int W[100005],C[100005];
    cin>>n>>m;
    for(int i = 0;i<n;i++)
        cin>>W[i];
    for(int i = 0;i<m;i++)
        cin>>C[i];
    sort(W,W+n,high);
    sort(C,C+m,high);
    int t = 0,total = 0,i=0;
    while(i!=m&&t!=n){
        if(C[i]>=W[t]){
            total+= W[t];
            i++,t++;
        }else if(C[i]<W[t]){
            t++;
        }
    }
    cout<<total<<endl;
}
更新於 閱讀次數

用實際行動犒賞爆肝的我😀

Zrn Ye LinePay

LinePay