CH 5105枚のクッキー(貪欲+ DP)

\(CH 5105枚のクッキー\)



\(溶液:\)

本当に良い質問!この質問は、私は長い、長い時間のために、あなたは完全に貪欲ことができますが、最終的には失敗したが、また、深い最適解と引き換えに貪欲スキームを考えて、その質問を指示しなければならないと思います。問題はその後DPはまた、非常に技術をテスト!

1貪欲:まず最初に、その時点で貪欲な質問です。まず、関係なく、欲の度合いのすべての子供は、限り、我々はにお菓子になるように\(N \)のコピー、実際には、あまり他の子供の数よりも彼らのキャンディーの数があるでしょうどのように多くの子供たちが決定されました。だから私たちは小さな子供の貪欲貪欲は何他のいくつかのお菓子を行うには聞かせてどのように子どもたちよりも多くの子供たちが少ないです。(これは倫理的に正当化することはできませんが)

2貪欲、それはデータの範囲を減らすことができますいくつかのお菓子の子供の数は、それが自分たちの中で恨みを生成しないようならば。私たちはお菓子の平均を共有する際に、少なくとも恨みは(つまり、何も不満はありません)が発生しました。しかし、お菓子の私達の平均数は必ずしもないが、我々はまだ貪欲な人は、できるだけお菓子の同じ数を作ることができます。:第二に、我々は考えることができお菓子が平均でない場合には、少数の人々は彼らのお菓子が皆より低いカウントがなければなりません!我々は非常に自然なアイデアを生み出すことができるように:まず、平均スコアを、すべての子どもたちが、余分なお菓子を取得するように、十分な数のままにすると、そのほかの子供たちに口の中に小さな子供の帝国貪欲に戻ってからお菓子を子供の他の子供たちに加えて、そう確かに、最高の平均(本当に不公平ああ)です。しかし、我々はまた、子供の背中には、すべてのお菓子を作ることができます保証することはできません(子供の他の子供たちを除いて平均値です)。しかし、この場合(M> N ^ 2 \) \ 時間を保証することができ、私たちはほとんどができる\(m個\)制限\(N ^ 2 \) その後、データが私たちに以下の範囲では、還元されその後、ブロガーはCHで最適解を得ました。

その後、我々は最初の子供のお菓子の貪欲、貪欲少し少ないし、我々は見つけるポイントを考える必要があるため、DP、DPが考えることはより困難な問題を解決するの話を、私たちは貪欲の降順ソートを、従っています我々は、線形DPの要件を満たしています。私が設定することができます\(F [i]の[jは ] \) 正面を示す\(私は\)と子\(j個の\を)キャンディ部分を。しかし、この問題はDPも迅速に転送することは困難(、それは通常の転送がかかる場合は、私たちをタイムアウト我々は二貪欲でデータ範囲を減らす場合、また、過去に実行することができます)。だから我々は、最適化する必要があり、今回はそのためあまりお菓子の小さなシェア一部の欲の後ろの子として見つかったので、我々は、この移動することができます:最初の場合は\(I + 1 \)最初よりも子供\(私は\)子供たちを少しお菓子を取得し、その後、これはかつてと同じです\(私は\)子どもたちはより多くのであり、(これらの二つの考え方は同じです)キャンディーを取りました。そして、伝達方程式は次のようになります。

\(F [I] [J] = \ {^ {F [i]が[JI]} _ {^ {分} _ {0 \当量のK <I} \ {F [K] [J-(IK)] + K・(S [i]が-S [K])\}} \)

注:\(S [I] \)前方表す\(私は\)貪欲な子の合計を。



\(コード:\)

#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;
}

おすすめ

転載: www.cnblogs.com/812-xiao-wen/p/11010537.html