ryo’s blog

日々学んだことをまとめています.

競プロ典型90問 048(★3) 貪欲法

048 - I will not drop out(★3)

問題

N 問, K 分間, 満点 A 点, 部分点 B 点(部分点は満点未満, 半分より大きい)

つまり \frac{A_i}{2} \lt B_i \lt A_i を満たす。

1分で部分点, 2分で満点が取れる。

K 分間で得られる最大得点を求める。

解法

得点方法は2パターン。

B 点取る or B 点取ってあるとこから、A - B 点取る。

後はsortして上から貪欲に選んでいく。

所感

最初にpairでsortしてから全探索したが上手くいかなかった。

全探索だと決めつけてしまい時間がかかった。

冷静に考えてみると、満点でも得られる点数は部分点より小さいため、 前計算してから同じ配列に入れて、大きい順に取るだけで大丈夫だった。

上手く行かないときは異なる視点から考えるようにしたい。

コード

#include <bits/stdc++.h>
#define rep(i,n) for (int i = 0; i < (n); ++i)
using namespace std;
using ll = long long;
using P = pair<int, int>;
struct fast_ios { fast_ios(){ cin.tie(nullptr), ios::sync_with_stdio(false), cout << fixed << setprecision(20); }; } fast_ios_;
const int INF = (int)1e9;
const ll INFL = (ll)1e18;
const int MOD = 1e9 + 7;
const double EPS = 1e-10;
int dx[]={0, 0, -1, 1};
int dy[]={1, -1, 0, 0};
template<class T> inline bool chmax(T& a, T b) { if (a < b) { a = b; return true; } return false; }
template<class T> inline bool chmin(T& a, T b) { if (a > b) { a = b; return true; } return false; }

int main()
{
    ll n, k, ans = 0;
    cin >> n >> k;
    vector<ll> vec;
    rep(i,n)
    {
        ll a, b;
        cin >> a >> b;
        vec.push_back(b);
        vec.push_back(a - b);
    }
    sort(vec.rbegin(), vec.rend());
    rep(i,k) ans += vec[i];
    cout << ans << endl;
    return 0;
}