Codeforces Round #437 Div. 2 C. Ordering Pizza (貪心經典)
阿新 • • 發佈:2018-12-13
思路來源
題意
N個人,每個比薩S塊,有兩種比薩,
每個人i,需要吃披薩si塊,吃比薩1會得到ai快樂值,吃比薩2會得到bi快樂值。
在提供比薩數最小,以確保所有人都有比薩吃的情況下,
問最大的快樂值。
題解
先理想化最大收益,然後貪心地使損失最小。
這是貪心題中的一種經典題。
先假設每人都吃的使自己快樂值最大那塊,
期間記錄下:若改披薩吃則不得不損失的快樂值和對應的塊數,
分別存進to1(2->1)和to2(1->2)優先佇列,按損失快樂值排序,若不得以而損失,先選損失快樂值少的。
最後num1%=s,num2%=s,剩下的不足s的,若加一起超過s說明需要兩塊,這樣最大收益可達。
否則小於s,這樣一塊比薩就可以滿足,即一部分人不得不犧牲選擇另一種披薩。
分別列舉這塊比薩是比薩1和比薩2,然後統計優先佇列裡的損失快樂值cost以湊齊塊數。
最後答案就是max(ans-cost1,ans-cost2).
心得
很經典的貪心題,
之前也見過這種先貪最大答案,然後一步步,退而求其次的。
先wa一發爆int了可還行,應該超過s就mod s的,就不用開long long了。
程式碼
#include <iostream> #include <algorithm> #include <string> #include <cstring> #include <cstdio> #include <cmath> #include <set> #include <map> #include <vector> #include <stack> #include <queue> #include <bitset> const int INF=0x3f3f3f3f; const int maxn=1e5+5; const int mod=1e9+7; const double eps=1e-7; typedef long long ll; #define vi vector<int> #define si set<int> #define pii pair<ll,ll> #define pi acos(-1.0) #define pb push_back #define mp make_pair #define lowbit(x) (x&(-x)) #define sci(x) scanf("%d",&(x)) #define scll(x) scanf("%lld",&(x)) #define sclf(x) scanf("%lf",&(x)) #define pri(x) printf("%d",(x)) #define rep(i,j,k) for(int i=j;i<=k;++i) #define per(i,j,k) for(int i=j;i>=k;--i) #define mem(a,b) memset(a,b,sizeof(a)) using namespace std; ll ans,n,s,a[maxn],b[maxn],num1,num2; priority_queue<pii,vector<pii>,greater<pii> >to1,to2;//to1表示2->1,to2表示1->2 void init() { ans=0;num1=0;num2=0; while(to1.size())to1.pop(); while(to2.size())to2.pop(); mem(a,0),mem(b,0); } int main() { while(~scanf("%lld%lld",&n,&s)) { init(); rep(i,0,n-1) { ll s,a,b; scanf("%lld%lld%lld",&s,&a,&b); if(a>b) { num1+=s; ans+=s*a; to2.push(pii(a-b,s));//表明向2轉化的cost,先轉化浪費少的 } else { num2+=s; ans+=s*b; to1.push(pii(b-a,s)); } } num1%=s,num2%=s;//正好的就用s裝,剩下的部分最多兩個s就能裝得下 if(num1+num2>s)//需要兩個 不需要轉化 { printf("%lld\n",ans); continue; } else { ll tmp1=num1,tmp2=num2,cost1=0,cost2=0; while(tmp1)//將1全轉化為2 { pii tmp=to2.top(); to2.pop(); ll num=min(tmp1,tmp.second); tmp1-=num; cost1+=num*tmp.first; } while(tmp2) { pii tmp=to1.top(); to1.pop(); int num=min(tmp2,tmp.second); tmp2-=num; cost2+=num*tmp.first; } printf("%lld\n",max(ans-cost1,ans-cost2)); } } return 0; }