contest hunter5105cookies(dp)

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

输入格式
第一行两个整数N,M,第二行N个整数g1~gN。

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

样例输入
样例输入1
3 20
1 2 3

样例输入2
4 9
2 1 5 8
样例输出
样例输出1
2
2 9 9

样例输出2
7
​2 1 3 3
来源
ITMO


简单dp

#include<bits/stdc++.h>
using namespace std;
#define rep(i,j,k) for(int i = j;i <= k;++i)
#define repp(i,j,k) for(int i = j;i >= k;--i)
#define rept(i,x) for(int i = linkk[x];i;i = e[i].n)
#define P pair<int,int>
#define Pil pair<int,ll>
#define Pli pair<ll,int>
#define Pll pair<ll,ll>
#define pb push_back 
#define pc putchar
#define mp make_pair
#define file(k) memset(k,0,sizeof(k))
#define fr first
#define se second
#define ll long long
int f[31][5010];//i个人分j个
int n,m;
struct data{
    int id,num;
}g[31];
P from[31][5010];
int sum[31] , ans[31];
int read()
{
    int sum = 0;char c = getchar();bool flag = true;
    while(c < '0' || c > '9') {if(c == '-') flag = false;c = getchar();}
    while(c >= '0' && c <= '9') sum = sum * 10 + c - 48,c = getchar();
    if(flag) return sum;
    else return -sum;
}
bool mycmp(data a,data b)
{
    return a.num > b.num;
}
int main()
{
    n = read();m = read();rep(i,0,n) rep(j,0,m) f[i][j] = 1e9;
    rep(i,1,n) g[i].num = read() , g[i].id = i;
    sort(g+1,g+n+1,mycmp);
    rep(i,1,n) sum[i] = sum[i-1] + g[i].num;
    f[0][0] = 0;
    rep(i,1,n)
        rep(j,i,m)
        {
            f[i][j] = f[i][j-i];
            from[i][j].fr = i;from[i][j].se = j-i;
            rep(k,0,i-1)
            {
                int tmp = sum[i] - sum[k];tmp*=k;
                if(f[k][j-i+k]+tmp < f[i][j])
                {
                    f[i][j] = f[k][j-i+k] + tmp;
                    from[i][j].fr = k;from[i][j].se = j-i+k;
                }
            }
        }
    printf("%d\n",f[n][m]);
    P now;
    now.fr = n;now.se = m;
    int det = 0;
    while(now.fr != 0)
    {
        int x = now.fr,y = now.se;
        if(from[x][y].fr == x) det++;
        else if(from[x][y].fr == x-1)ans[g[x].id] = y - from[x][y].se + det;
        else if(from[x][y].fr < x-1)
        {
            rep(i,from[x][y].fr+1,x) ans[g[i].id] = 1 + det;
        }
        now = from[x][y];
    }
    rep(i,1,n) printf("%d ",ans[i]);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/a1035719430/article/details/82455924