ZOJ 4067 - Books - [貪心][2018 ACM-ICPC Asia Qingdao Regional Problem J]
阿新 • • 發佈:2018-11-10
題目連結:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=4067
題意:
給出 $n$ 本書(編號 $1 \sim n$),第 $i$ 本書的價格為 $a_i$ 元。我現在手上有若干元錢,我買書的策略為從 $1 \sim n$ 依次買書,若遇到價格不超過我手上錢數的,我就買下,否則就跳過。
現在已知我買了 $m$ 本書,請求出我手上最多有多少元錢。
Sample Input
4 4 2 1 2 4 8 4 0 100 99 98 97 2 2 10000 10000 5 3 0 0 0 0 1
Sample Output
6 96 Richman Impossible
題解:
(這題剛開始想了個二分的假演算法……WA了好多發,瘋狂演隊友,然後在我找不出任何二分哪裡錯了的絕望時刻,隊友力挽狂瀾想出了下面的思路QAQ)
假設我手上有 $k$ 元,我若某次在遇到書 $A$ 時跳過了而之後買了 $B$,顯然價格上 $A>B$。
因此我手上只有多過 $k$ 元,才能買下 $A$,從而不買 $B$。換句話說,當我一本書都不跳過的時候,才是我的錢最多的時候。
所以,先去掉所有價格為 $0$ 的書,這些是白送的我肯定會買。剩下來要花錢買 $m-cnt_{price=0}$ 本書,即買前 $m-cnt_{price=0}$ 本書;然後再在其餘的書中找價格最低的那一本,其價格減去 $1$,加上即可。
AC程式碼:
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int maxn=1e5+10; int n,m; ll a[maxn]; int main() { ios::sync_with_stdio(0); cin.tie(0); int T; cin>>T; while(T--) { cin>>n>>m; int cnt0=0; for(int i=1;i<=n;i++) cin>>a[i], cnt0+=(a[i]==0); if(n<=m) cout<<"Richman\n"; else if(cnt0>m) cout<<"Impossible\n"; else { m-=cnt0; ll mn=0x3f3f3f3f, ans=0; for(int i=1;i<=n;i++) { if(a[i]==0) continue; if(m) ans+=a[i], m--; else mn=min(mn,a[i]); } cout<<ans+mn-1<<'\n'; } } }