CH 5105 Cookies (greedy + DP)

\(CH 5105 Cookies\)



\(solution:\)

A really good question! This question I think for a long, long time, you have to direct that question can completely greedy, but finally failed, but also deep thinking greedy scheme in exchange for an optimal solution. The question then DP also test the very technology!

Greedy 1: The first thing is greedy questions at that time. First, every child regardless of the degree of greed, as long as we will be candy into \ (N \) copies, in fact, it has been determined how many children there will be a number of their candy less than the number of other children. So we let the greedy greed of a small child to do what several other candy how many children less than children. (Although this can not be justified ethically)

Greedy 2, it can reduce the data range: If the number of children of some candy as it does not generate resentment among themselves. So when we will be sharing candy average, the least resentment generated (that is, no grievances). But our average number of candy does not necessarily, but we can still greedy people make the same number of sweets as much as possible. Second, we can think of: If candy is not average, then there must be a few people count their candy is lower than everyone else! So that we can produce a very natural idea: first, the average score, if a few left enough so that all children get an extra candy, candy from back to Imperial greed of a small child in the mouth to the other children so in addition to the child's other children are average (really really unfair ah), so certainly the best. But we also can not guarantee the child's back can make all the candy (except for the child's other children are average). However, this case in (m> n ^ 2 \) \ time can be guaranteed , we can mostly \ (m \) limit \ (n ^ 2 \) or less, then the data range to us is the reduction, then bloggers got the optimal solution on the CH. . . . . .

Then talk about DP, DP solving the problem more difficult to think, because we first need to think of a greedy, greedy little less then we find points of kids candy, so we follow the descending sort of greed, which we meet the requirements of the linear DP. I can set up \ (F [i] [j ] \) shows a front \ (i \) a child with a \ (j \) pieces of candy. However, this problem DP also difficult to quickly transfer , we If it takes a lot of normal transfers, time out ( if we reduce the data range with a second greedy, can also run in the past ). So we need to optimize, this time we found that as the children behind because of the greed of some small a share of less candy, so we can move this: If the first \ (i + 1 \) child than the first \ (i \) children get a little candy, then this is equivalent to the former \ (i \) children are more and took a candy (these two ideas are equivalent). Then transfer equation becomes:

\(F[i][j]=\{^{F[i][j-i]}_{^{ min}_{0\leq k<i}\{F[k][j-(i-k)]+k*(S[i]-S[k]) \}}\)

Note: \ (S [I] \) representing the forward \ (I \) the sum of the greedy child.



\(code:\)

#include<iostream>
#include<cstdio>
#include<iomanip>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<ctime>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<set>

#define ll long long
#define db double
#define inf 0x7fffffff
#define rg register int

using namespace std;

int n,m;
int S[35];
int as[35];
int f[35][905];

struct su{
    int da,id;
    inline bool operator <(const su &x)const{return da>x.da;}
}a[35];

struct pi{
    int x,y;
}d[35][905];

inline int qr(){
    register char ch; register bool sign=0; rg res=0;
    while(!isdigit(ch=getchar())) if(ch=='-')sign=1;
    while(isdigit(ch)) res=res*10+(ch^48),ch=getchar();
    return sign?-res:res;
}

inline void tepan(){
    printf("%d\n",a[n].da*(n-1));
    rg ans=m/n,res=m%n;
    for(rg i=1;i<n;++i) as[a[i].id]=ans+bool(res);
    as[a[n].id]=ans; if(res) as[a[n].id]-=n-res-1;
    for(rg i=1;i<=n;++i) printf("%d ",as[i]);
    puts(""); exit(0);
}

inline void print(int i,int j){
    if(i==0)return ;
    else print(d[i][j].x,d[i][j].y);
    if(d[i][j].x==i) for(rg k=1;k<=i;++k)++as[a[k].id];
    else for(rg k=d[i][j].x+1;k<=i;++k)++as[a[k].id];
}

int main(){
    //freopen(".in","r",stdin);
    //freopen(".out","w",stdout);
    n=qr(); m=qr();
    for(rg i=1;i<=n;++i)
        a[i].da=qr(),a[i].id=i;
    sort(a+1,a+n+1); if(m>n*n)tepan();
    for(rg i=1;i<=n;++i) S[i]=S[i-1]+a[i].da;
    for(rg i=1;i<=m;++i) f[0][i]=1e9;
    for(rg i=1;i<=n;++i){
        for(rg j=0;j<=m;++j){
            if(j<i){f[i][j]=1e9; continue;}
            f[i][j]=f[i][j-i]; d[i][j].x=i; d[i][j].y=j-i;
            for(rg k=0;k<i;++k){
                rg tot=f[k][j-(i-k)]+k*(S[i]-S[k]);
                if(tot<f[i][j])f[i][j]=tot,d[i][j].x=k,d[i][j].y=j-(i-k);
            }
        }
    } printf("%d\n",f[n][m]); print(n,m);
    for(rg i=1;i<=n;++i) printf("%d ",as[i]);
    puts(""); return 0;
}

Guess you like

Origin www.cnblogs.com/812-xiao-wen/p/11010537.html