競プロ典型90問 048(★3) 貪欲法
問題
N 問, K 分間, 満点 A 点, 部分点 B 点(部分点は満点未満, 半分より大きい)
つまり を満たす。
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; }