列表

详情


NC51156. Cookies

描述

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

输入描述

第一行两个整数N,M,第二行N个整数

输出描述

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

示例1

输入:

3 20
1 2 3

输出:

2
2 9 9

示例2

输入:

4 9
2 1 5 8

输出:

7
2 1 3 3

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++(g++ 7.5.0) 解法, 执行用时: 6ms, 内存消耗: 1576K, 提交时间: 2022-08-10 14:15:05

#include <bits/stdc++.h>
using namespace std;
typedef pair<int,int> PII;
const int N=35,M=5005;
int f[N][M],n,m,ans[N],b[N][M];
PII a[N];
int main()
{
    cin>>n>>m;
    memset(f,0x3f,sizeof f);
    for(int i=1; i<=n; i++)
        cin>>a[i].first, a[i].second=i;
    sort(a+1,a+1+n,greater<PII>());
    for(int i=1; i<=n; i++)
        a[i].first+=a[i-1].first, f[i][0]=0;
    for(int i=1; i<=n; i++)
        for(int j=i; j<=m; j++) {
            f[i][j]=f[i][j-i];
            b[i][j]=n+1;
            for(int k=0; k<i; k++) {
                int s=f[k][j-i+k]+k*(a[i].first-a[k].first);
                if(f[i][j]<=s)continue;
                f[i][j]=s;
                b[i][j]=k;
            }
        }
    cout<<f[n][m]<<endl;
    int i=n, j=m, h=0;
    while(i)
    {
        int k=b[i][j];
        for(int u=i; u>k; u--)
            ans[a[u].second]=(k ? h+1 : h);
        if(k<=n) j-=i-k, i=k;
        else if(j>=i)
            j-=i, h++;
    }
    for(i=1;i<=n;i++)cout<<ans[i]<<" ";
    cout << endl;
}

C++14(g++5.4) 解法, 执行用时: 8ms, 内存消耗: 2424K, 提交时间: 2020-08-05 15:49:12

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int N=50,M=5e3+10;
int f[N][M],g[N],id[N],sum[N],cnt[N][M],hav[N][M],ans[N];
int cmp(const int &a,const int &b){return g[a]>g[b];}
void print(int n,int m)
{
	if(!n)return;
	print(cnt[n][m],hav[n][m]);
	if(cnt[n][m]==n)for(int i=1;i<=n;i++)ans[id[i]]++;
	else for(int i=cnt[n][m]+1;i<=n;i++)ans[id[i]]=1;
}
int main()
{
    int n,m;
	scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)scanf("%d",&g[i]),id[i]=i;
    sort(id+1,id+n+1,cmp);
    memset(f,0x3f,sizeof(f));
    f[0][0]=0;
	for(int i=1;i<=n;i++)
	{
	    sum[i]=sum[i-1]+g[id[i]];
		for(int j=i;j<=m;j++)
	    {
	    	f[i][j]=f[i][j-i];cnt[i][j]=i;hav[i][j]=j-i;
	    	for(int k=0;k<i;k++)
	    	    if(f[i][j]>f[k][j-(i-k)]+(sum[i]-sum[k])*k)
	    	    {
	    	    	f[i][j]=f[k][j-(i-k)]+(sum[i]-sum[k])*k;
	    	    	cnt[i][j]=k;hav[i][j]=j-(i-k);
				}
		}
	}
	printf("%d\n",f[n][m]);
	print(n,m);
	for(int i=1;i<=n;i++)printf("%d%c",ans[i],i==n?'\n':' ');
	return 0;
}

C++ 解法, 执行用时: 10ms, 内存消耗: 3596K, 提交时间: 2022-01-10 09:16:31

#include<bits/stdc++.h>
using namespace std;
int n,m,i,j,k,f[101][5001],s[101],g[101],a[101][5001],b[101][5001],ans[5001],c[101];
int cmp(int a,int b){return g[a]>g[b];}
void print(int n,int m){
	if(!n)return;
	print(a[n][m],b[n][m]);
	if(a[n][m]==n)for(int i=1;i<=n;i++)ans[c[i]]++;
	else for(int i=a[n][m]+1;i<=n;i++)ans[c[i]]=1;
}
int main(){
    cin>>n>>m;
    for(int i=1;i<=n;i++)cin>>g[i],c[i]=i;
    sort(c+1,c+1+n,cmp);
    memset(f,0x3f,sizeof(f));
    f[0][0]=0;
    for(int i=1;i<=n;i++){
		s[i]=s[i-1]+g[c[i]];
		for(int j=i;j<=m;j++){
			f[i][j]=f[i][j-i];
			a[i][j]=i;
			b[i][j]=j-i;
			for(int k=0;k<i;k++)if (f[i][j]>f[k][j-(i-k)]+(s[i]-s[k+1-1])*k){
				f[i][j]=f[k][j-(i-k)]+(s[i]-s[k+1-1])*k;
				a[i][j]=k;
				b[i][j]=j-(i-k);
			}
		}
	}
	cout<<f[n][m]<<"\n";
    print(n,m);
	for(int i=1;i<=n;i++)cout<<ans[i]<<' ';
    return 0;
}

上一题