Cookies

CH

题意:圣诞老人共有(M)个饼干,准备全部分给(N)个孩子.每个孩子有一个贪婪度,第(i)个孩子的贪婪度为(g[i]).如果有(a[i])个孩子拿到的饼干数比第(i)个孩子多,那么第 (i)个孩子会产生(g[i]*a[i])的怨气.给定(N、M)和序列(g),圣诞老人请你帮他安排一种分配方式,使得每个孩子至少分到一块饼干,并且所有孩子的怨气总和最小,求最小怨气和以及任意一种方案.(1≤N≤30,N≤M≤5000,1<=g[i]<=10^7)

分析:设(f[i][j])表示前i个人,分了j块饼干,所产生的最小的贪婪值.

先把所有人按照贪婪度从大到小排序,保证分的饼干数单调递减(这个贪心策略不要证明也能理解吧).

既然保证了单调性,那就好写转移方程.分两种情况讨论.

如果第i个人分的饼干数大于1,那么等价于前i个人分了j-i个饼干,即每个人少拿一块饼干(这样做相对大小不变,所以贪婪值也不会变,不影响结果):

(f[i][j]=f[i][j-i])

如果第i个人获得的饼干数为1,则枚举i前面有多少个人也获得1块饼干:

(f[i][j]=min_{0<=k<i} f[k,j-(i-k)]+k*sum_{p=k+1}^i g[p])

初始化(f[0][0]=0),其余赋值为正无穷.目标(f[n][m])

题目还要求方案,再开一个(pre[i][j])表示前i个人,分了j块饼干时的转移路径.

如果(f[i][j]=f[i][j-i]),则(pre[i][j]=i)

如果是另一种情况,则(pre[i][j]=k)

如何输出方案时,同理也要分情况讨论,详见代码.

#include<bits/stdc++.h>
using namespace std;
inline int read(){
    int s=0,w=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){s=s*10+ch-'0';ch=getchar();}
    return s*w;
}
const int N=35;
int sum[N],ans[N],f[N][5005],pre[N][5005];
struct ppx{
    int g,num;
}a[N];
inline bool cmp(const ppx &x,const ppx &y){return x.g>y.g;}
int main(){
    int n=read(),m=read();
    for(int i=1;i<=n;i++)a[i].g=read(),a[i].num=i;
    sort(a+1,a+n+1,cmp);
    for(int i=1;i<=n;i++)sum[i]=sum[i-1]+a[i].g;
    memset(f,0x3f,sizeof(f));f[0][0]=0;
    for(int i=1;i<=n;i++)
		for(int j=i;j<=m;j++){
	    	f[i][j]=f[i][j-i];pre[i][j]=i;
	    	for(int k=0;k<i;k++)
				if(f[i][j]>f[k][j-(i-k)]+k*(sum[i]-sum[k])){
		    		f[i][j]=f[k][j-(i-k)]+k*(sum[i]-sum[k]);
		    		pre[i][j]=k;
				}
		}
    printf("%d
",f[n][m]);
//输出方案:(DP如何分类如何转移,输出方案时也同样做)
    int nn=n,mm=m;
    while(nn){
//如果是第一种情况,根据上述分析,把每个人的饼干数减1是等价的,所以每个人都可以分到一块饼干
		if(pre[nn][mm]==nn){
	    	for(int i=1;i<=nn;i++)ans[a[i].num]++;
	    	mm-=nn;
		}
//情况2,只有k+1到n分的饼干数一样,就一起处理,每个人都可以分到一块饼干.
		else{
	    	for(int i=pre[nn][mm]+1;i<=nn;i++)ans[a[i].num]++;
	    	int k=pre[nn][mm];mm=mm-(nn-k);nn=k;
		}
    }
    for(int i=1;i<=n;i++)printf("%d ",ans[i]);puts("");
    return 0;
}

原文地址:https://www.cnblogs.com/PPXppx/p/10990714.html