Never be limited by other pe|

zyc_xianyu

园龄:3年7个月粉丝:4关注:4

饼干(算法竞赛进阶指南)

圣诞老人共有 M 个饼干,准备全部分给 N 个孩子。

每个孩子有一个贪婪度,第 i 个孩子的贪婪度为 g[i]。

如果有 a[i] 个孩子拿到的饼干数比第 i 个孩子多,那么第 i 个孩子会产生 g[i]×a[i] 的怨气。

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

输入格式

第一行包含两个整数 N,M。

第二行包含 N 个整数表示 g1∼gN。

输出格式

第一行一个整数表示最小怨气总和。

第二行 N 个空格隔开的整数表示每个孩子分到的饼干数,若有多种方案,输出任意一种均可。

数据范围

1≤N≤30,

N≤M≤5000,

1≤gi≤107

输入样例:

3 20

1 2 3

输出样例:

2

2 9 9

这道题我感觉和以前做过的线性DP有所不同,以前的可以找到一个固定的趋势,但这道题明显更灵活。

换句话说,这道题的范围实在太大了,我们要想办法减少计算的范围。怎么办?

如何在所有分配方案中找到有着最优解的局部分配方案?用贪心的思想。

将所有小朋友按愤怒值g[i]从大小到小排序,排名靠前的小朋友分配的饼干要更多一些。
 

如果总有一些孩子无法满足,那么我们可以想到控制分饼干的数目,最后吃亏的孩子拿到的饼干数量是固定的,乘以贪婪度时显然贪婪度越低值越小。

首先将所有小朋友按g[i]从大到小排序。

这道题成功转化为先前类似的题,我们能感受到到转态转移的趋势是固定的。

 转载于:AcWing 277. 饼干 - AcWing

 

#include<bits/stdc++.h>

using namespace std;

typedef pair<int, int> PII;

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);
	
	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 ++)
			f[i][j] = min(f[i][j],f[i - k][j - k] + (s[i] - s[i - k]) * (i - k));//给1-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;
}

本文作者:zychh

本文链接:https://www.cnblogs.com/zychh/p/16726677.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   zyc_xianyu  阅读(61)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起