ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

AcWing277 Cookies 饼干

2022-04-06 18:34:43  阅读:131  来源: 互联网

标签:Cookies 饼干 rep 孩子 sum id maxn AcWing277


题目大意

圣诞老人共有 \(M\) 个饼干,准备全部分给 \(N\) 个孩子。每个孩子有一个贪婪度,第 \(i\) 个孩子的贪婪度为 \(g_i\)。如果有 \(a_i\) 个孩子拿到的饼干数比第 \(i\) 个孩子多,那么第 \(i\) 个孩子会产生 \(g_i\times a_i\) 的怨气。

给定 \(N\)、\(M\) 和序列 \(g\),圣诞老人请你帮他安排一种分配方式,使得每个孩子至少分到一块饼干,并且所有孩子的怨气总和最小。\(N\le 30\),\(N\le M\le 5000\)。

大体思路

考虑动态规划加贪心。由贪心可得,\(g\) 更大的孩子分得的饼干数量一定不小于 \(g\) 较小的孩子。

利用反证法。不妨怨气值最小时设存在 \(i,j\) 使得 \(g_i>g_j\),所拥有的饼干数量 \(h_i<h_j\),则交换 \(h_i,h_j\) 后,对于其他孩子来说怨气总和不变,而这两个孩子的怨气之和减少了 \(g_i-g_j\),矛盾。

所以,我们可以对 \(g\) 从大到小进行排序,然后设 \(F(i,j)\) 表示前 \(i\) 个孩子一共分了 \(j\) 块饼干的最小怨气值之和。我们考虑第 \(i\) 个孩子的饼干分得的情况。

若第 \(i\) 个人分得 \(>1\) 块,则所有人减去 \(1\) 块后怨气值不变,因此 \(F(i,j)=F(i,j-i)\)。

若第 \(i\) 个人分得 \(1\) 块,则不能减去 \(1\),因此枚举最小的不是 \(1\) 块的编号 \(k\),然后 \(1\sim k\) 称为一个子问题,\(k+1\sim i\) 的块数均为 \(1\)。

\[F(i,j)=\min\begin{cases}F(i,j-i)\\\min_{0\le k<i}\{F(k,j-i+k)+k\times\sum_{l=k+1}^i g_l\}\end{cases} \]

image

记录每一次 \(i,j\) 的转移,递归输出方案即可。

#include <bits/stdc++.h>
using namespace std;
#define rep(ii,aa,bb) for(re int ii = aa; ii <= bb; ii++)
#define Rep(ii,aa,bb) for(re int ii = aa; ii >= bb; ii--)
typedef long long ll;
typedef unsigned long long ull;
typedef double db;
typedef pair<ll, ll> PII;
const int maxn = 5e3 + 5;
namespace IO_ReadWrite {
	#define re register
	#define gg (p1 == p2 && (p2 = (p1 = _buf) + fread(_buf, 1, 1<<21, stdin), p1 == p2) ? EOF :*p1++)
	char _buf[1<<21], *p1 = _buf, *p2 = _buf;
	template <typename T>
	inline void read(T &x){
		x = 0; re T f=1; re char c = gg;
		while(c > 57 || c < 48){if(c == '-') f = -1;c = gg;}
		while(c >= 48 &&c <= 57){x = (x<<1) + (x<<3) + (c^48);c = gg;}
		x *= f;return;
	}
	inline void ReadChar(char &c){
		c = gg;
		while(!isalpha(c)) c = gg;
	}
	template <typename T>
	inline void write(T x){
		if(x < 0) putchar('-'), x = -x;
		if(x > 9) write(x/10);
		putchar('0' + x % 10);
	}
	template <typename T>
	inline void writeln(T x){write(x); putchar('\n');}
}
using namespace IO_ReadWrite;
ll f[35][maxn], n, m, sum[maxn];
ll I[31][maxn], J[31][maxn], a[maxn], id[maxn];
struct node {
	ll val, id;
	bool operator <(const node &x)const{
		return val > x.val;
	}
} g[maxn];
inline void work(int i, int j) {
	if(!i) return;
	work(I[i][j], J[i][j]);
	if(I[i][j] == i)
		rep(t, 1, i) a[t] ++;
	else rep(t, I[i][j] + 1, i) a[t] = 1;
}
int main () {
	read(n); read(m);
	rep(i, 1, n) read(g[g[i].id = i].val);
	sort(g + 1, g + n + 1);
	rep(i, 1, n)
		sum[i] = sum[i - 1] + g[i].val,
		id[g[i].id] = i;
	memset(f, 0x3f, sizeof f);
	f[0][0] = 0;
	rep(i, 1, n) 
		rep(j, i, m) {
			f[i][j] = f[i][j - i];
			I[i][j] = i, J[i][j] = j - i;
			rep(k, 0, i - 1) 
				if(f[k][j - (i - k)] + k * (sum[i] - sum[k]) < f[i][j]) {
					f[i][j] = f[k][j - (i - k)] + k * (sum[i] - sum[k]);
					I[i][j] = k;
					J[i][j] = j - (i - k);
				}
		}
	writeln(f[n][m]);
	work(n, m);
	rep(i, 1, n) write(a[id[i]]), putchar(' ');
	return 0;
}

标签:Cookies,饼干,rep,孩子,sum,id,maxn,AcWing277
来源: https://www.cnblogs.com/Mars-LG/p/AcWing277.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有