Acwing 277. 饼干
生活随笔
收集整理的這篇文章主要介紹了
Acwing 277. 饼干
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
Acwing 277. 餅干
題意:
圣誕老人共有 M 個餅干,準備全部分給 N 個孩子。
每個孩子有一個貪婪度,第 i 個孩子的貪婪度為 g[i]。
如果有 a[i] 個孩子拿到的餅干數比第 i 個孩子多,那么第 i 個孩子會產生 g[i]×a[i] 的怨氣。
給定 N、M 和序列 g,圣誕老人請你幫他安排一種分配方式,使得每個孩子至少分到一塊餅干,并且所有孩子的怨氣總和最小。
1≤N≤30,
N≤M≤5000,
1≤gi≤10710^7107
題解:
一個孩子的怨氣大小與其他孩子獲得的餅干數有關,通過貪心分析不難發現,貪婪度大的孩子應該分到更多的餅干(也可以證明,此處略)
所以我們把N個孩子按照貪婪值從大到小排序,他們分配到的餅干數將是單調遞減的
代碼:
在代碼中是枚舉分到餅干數量為1的人數
#include<bits/stdc++.h> #define debug(a,b) printf("%s = %d\n",a,b); using namespace std; typedef long long ll; typedef pair<int, int> PII; //Fe~Jozky const ll INF_ll=1e18; const int INF_int=0x3f3f3f3f; inline ll read(){ll s=0,w=1ll;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')w=-1ll;ch=getchar();}while(ch>='0'&&ch<='9') s=s*10ll+((ch-'0')*1ll),ch=getchar();//s=(s<<3)+(s<<1)+(ch^48);return s*w; } void rd_txt(){#ifdef ONLINE_JUDGE#elsefreopen("in.txt","r",stdin);#endif } const int N = 31, M = 5010;int n, m; PII g[N]; int s[N]; int f[N][M]; int ans[N];int main() {cin >> n >> m;for (int i = 1; i <= n; i ++ ){cin >> g[i].first;g[i].second = i;}sort(g + 1, g + n + 1);reverse(g + 1, g + n + 1);//現在g是從大到小 for (int i = 1; i <= n; i ++ ) s[i] = s[i - 1] + g[i].first;memset(f, 0x3f, sizeof f);f[0][0] = 0;for (int i = 1; i <= n; i ++ )for (int j = 1; j <= m; j ++ ){if (j >= i) f[i][j] = f[i][j - i];for (int k = 1; k <= i && k <= j; k ++ )//枚舉的k是數量為1的人 f[i][j] = min(f[i][j], f[i - k][j - k] + (s[i] - s[i - k]) * (i - k));}cout << f[n][m] << endl;//根據結果反著推過程 int i = n, j = m, h = 0;while (i && j){if (j >= i && f[i][j] == f[i][j - i]) j -= i, h ++ ;else{for (int k = 1; k <= i && k <= j; k ++ )if (f[i][j] == f[i - k][j - k] + (s[i] - s[i - k]) * (i - k)){for (int u = i; u > i - k; u -- )ans[g[u].second] = 1 + h;i -= k, j -= k;break;}}}for (int i = 1; i <= n; i ++ ) cout << ans[i] << ' ';cout << endl;return 0; }總結
以上是生活随笔為你收集整理的Acwing 277. 饼干的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 路由器十大品牌排行榜 路由器品牌推荐
- 下一篇: 《算法竞赛进阶指南》 0x50 动态规划