#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\n",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