其他分享
首页 > 其他分享> > 饼干

饼干

作者:互联网

每个孩子有一个贪婪度,第 i 个孩子的贪婪度为 g[i]。
如果有 a[i] 个孩子拿到的饼干数比第 i 个孩子多,那么第 i 个孩子会产生 g[i]×a[i] 的怨气。
给定 N、M 和序列 g,圣诞老人请你帮他安排一种分配方式,使得每个孩子至少分到一块饼干,并且所有孩子的怨气总和最小。

注意到怨气值只和相对大小有关,而和绝对大小没有关系 可以考虑放缩来做
排序后
\(f[i][j]=f[i][j-i]\) 每个人去掉一块饼干不影响结果
\(f[i][j]=min\{f[i-k][j-k]+k*\sum_{p=k+1}^ig[p] \}\) 枚举最后有多少个饼干

由于最后是取最小值 所以即使状态之间有重叠,正确性仍然可以保证

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define pa pair<int,int>
#define mp make_pair
#define fs first
#define sc second
using namespace std;

const int N=35;
const int M=5050;
int read()
{
	int x=0,f=0,c=getchar();
	while(c<'0'||c>'9'){if(c=='-')f=1;c=getchar();}
	while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
	return f?-x:x;
}
struct Node
{
	int g,id;
}p[N];
bool cmp(Node a,Node b){return a.g>b.g;}
int sum[N],n,m;
int f[N][M],ans[N];
pa g[N][M];

void print(int x,int y,pa pp)
{
	if(!x) return;
	if( x==pp.fs) 
		for(int i=1;i<=x;i++) ans[p[i].id]++;
	else
		for(int i=pp.fs+1;i<=x;i++) ans[p[i].id]++;
	print(pp.fs,pp.sc,g[pp.fs][pp.sc]);
}


int main()
{
	n=read(); m=read();
	for(int i=1;i<=n;i++) p[i].g=read(),p[i].id=i;
	sort(p+1,p+n+1,cmp);
	for(int i=1;i<=n;i++) sum[i]=sum[i-1]+p[i].g;
//dp初始状态的分析 根据含义边界的值是多少 所以应该怎么去赋值 初始状态也要合法	
	memset(f,0x3f,sizeof f);
	
	for(int i=1;i<=n;i++)
		for(int j=i;j<=m;j++)
		{
			if(i==j){f[i][j]=0; continue;}
			for(int k=0;k<i;k++)
				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]),
				g[i][j]=mp(k,j-i+k);
			if(f[i][j-i]<f[i][j])
				f[i][j]=f[i][j-i],
				g[i][j]=mp(i,j-i);
		}
	printf("%d\n",f[n][m]);
	print(n,m,g[n][m]);
	for(int i=1;i<=n;i++) printf("%d ",ans[i]);
	return 0;
}

标签:饼干,int,孩子,pa,include,define
来源: https://www.cnblogs.com/juruoHBr/p/15874119.html