$ CH 5105 Cookies $



$ solution: $

真是好题一道!这道题我想了很久很久,就得这一题可以直接完全贪心,可惜最后还是失败了,但是对贪心的深入思考也换来了一个最优解方案。然后这一题的DP也考的很有技术!

贪心1:这一道题当时第一眼就是贪心。首先不管每一个孩子的贪婪度,只要我们将糖果分为 $ N $ 份,实际上就已经确定了会存在多少个孩子他们的糖果数比多少个其他孩子要少。于是我们贪心的让贪婪度小的孩子去做那些糖果数比多少个其他孩子要少的孩子。(虽然这在伦理上说不过去)

贪心2,它可以减少数据范围:如果某些孩子的糖果数一样那么他们彼此之间就不会产生怨气。所以当我们将糖果平均分时,产生的怨气最少(就是没有怨气)。但是我们的糖果数不一定就能平均分了,但是我们依旧可以贪心的让相同糖果数的人尽量多。其次我们可以想到:如果糖果不够平均分,那么一定存在几个人他们的糖果数比其他所有人都低!这样我们就能产生一个很自然的想法:先平均分,如果还剩下几个不够让所有的孩子在多拿一个糖果,就钦定从贪婪度嘴小的孩子里拿回糖果给其他的孩子使得除了这个孩子以外其他孩子都是平均分的(真的好不公平啊),这样肯定能最优。但是我们同样不能保证把这个孩子的所有糖果都拿回能使得(除了这个孩子以外其他孩子都是平均分的)。但是这种情况在 $ m>n^2 $ 的时候可以得到保证,多以我们可以将 $ m $ 限制在 $ n^2 $ 以内,于是数据范围就被我们消减了,然后博主就拿到了CH上的最优解。。。。。。

然后讲一下DP,这道题的DP比较难想,因为我们首先需要想到第一个贪心,然后我们发现贪婪度小的孩子分的糖果少,于是我们按照贪婪度从大到小排序,这就符合我们线性DP的要求了。我完全可以设 $ F[i][j] $ 表示前 $ i $ 个孩子用了 $ j $ 颗糖果。但是这一题DP也难快速转移,我们如果正常转移花费的时间很多,会超时(如果我们用第二个贪心减少数据范围,也可以跑过去)。于是我们需要优化,这时候我们发现由于后面的孩子因为贪婪度小分到的糖果少一些,于是我们可以转移一下:假如第 $ i+1 $ 个孩子比第 $ i $ 个孩子得到的糖果少一个,那么这就相当于前 $ i $ 个孩子都多拿了一个糖果(这两个想法是等效的)。于是转移方程变成了:

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

注: $ S[i] $ 表示前 $ i $ 个孩子的贪婪度总和。



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

CH 5105 Cookies(贪心+DP)的更多相关文章

  1. 【CH5105】cookies 贪心+DP

    通过邻项交换法可知,怨气值大的孩子分得的饼干数也应该多(否则交换之后得到的解更优). 观察目标函数的性质,可知目标函数本身是由孩子饼干数的相对大小得到,因此此题中关注的是相对大小. 状态设计:\(dp ...

  2. 【BZOJ-3174】拯救小矮人 贪心 + DP

    3174: [Tjoi2013]拯救小矮人 Time Limit: 1 Sec  Memory Limit: 128 MBSubmit: 686  Solved: 357[Submit][Status ...

  3. 洛谷P4823 拯救小矮人 [TJOI2013] 贪心+dp

    正解:贪心+dp 解题报告: 传送门! 我以前好像碰到过这题的说,,,有可能是做过类似的题qwq? 首先考虑这种显然是dp?就f[i][j]:决策到了地i个人,跑了j个的最大高度,不断更新j的上限就得 ...

  4. 贪心+DP【洛谷P4823】 [TJOI2013]拯救小矮人

    P4823 [TJOI2013]拯救小矮人 题目描述 一群小矮人掉进了一个很深的陷阱里,由于太矮爬不上来,于是他们决定搭一个人梯.即:一个小矮人站在另一小矮人的 肩膀上,知道最顶端的小矮人伸直胳膊可以 ...

  5. BZOJ_3174_[Tjoi2013]拯救小矮人_贪心+DP

    BZOJ_3174_[Tjoi2013]拯救小矮人_贪心+DP Description 一群小矮人掉进了一个很深的陷阱里,由于太矮爬不上来,于是他们决定搭一个人梯.即:一个小矮人站在另一小矮人的 肩膀 ...

  6. 【bzoj5073】[Lydsy1710月赛]小A的咒语 后缀数组+倍增RMQ+贪心+dp

    题目描述 给出 $A$ 串和 $B$ 串,从 $A$ 串中选出至多 $x$ 个互不重合的段,使得它们按照原顺序拼接后能够得到 $B$ 串.求是否可行.多组数据. $T\le 10$ ,$|A|,|B| ...

  7. 【bzoj3174】[Tjoi2013]拯救小矮人 贪心+dp

    题目描述 一群小矮人掉进了一个很深的陷阱里,由于太矮爬不上来,于是他们决定搭一个人梯.即:一个小矮人站在另一小矮人的 肩膀上,知道最顶端的小矮人伸直胳膊可以碰到陷阱口.对于每一个小矮人,我们知道他从脚 ...

  8. hdu 1257 最少拦截系统【贪心 || DP——LIS】

    链接: http://acm.hdu.edu.cn/showproblem.php?pid=1257 http://acm.hust.edu.cn/vjudge/contest/view.action ...

  9. 贪心+dp

    贪心+dp 好多题都是这个思想, 可以说是非常重要了 思想一: 在不确定序列无法dp的情况下, 我们不妨先假设序列已经选定, 而利用贪心使序列达到最优解, 从而先进行贪心排序, 在进行dp选出序列 思 ...

随机推荐

  1. iOS第三方地图-高德地图(导航sdk路径规划)

    @import url(http://i.cnblogs.com/Load.ashx?type=style&file=SyntaxHighlighter.css);@import url(/c ...

  2. 【Luogu】P1516青蛙的约会(线性同余方程,扩展欧几里得)

    题目链接 定理:对于方程\(ax+by=c\),等价于\(a*x=c(mod b)\),有整数解的充分必要条件是c是gcd(a,b)的整数倍. ——信息学奥赛之数学一本通 避免侵权.哈哈. 两只青蛙跳 ...

  3. 写给新员工的十点SQL开发建议

    1.建立自己的知识体系 摘抄一句话你所拥有的知识并不取决于你记得多少,而在于它们能否在恰当的时候被回忆起来: 做笔记: 把笔记放在可以随时被找到的地方.个人的笔记可以放在印象笔记之类工具上,单位上的笔 ...

  4. cf299C Weird Game

    Weird Game Yaroslav, Andrey and Roman can play cubes for hours and hours. But the game is for three, ...

  5. android获取手机号

    private String getPhoneNum(){ //与手机建立连接 TelephonyManager tm = (TelephonyManager)getSystemService(Con ...

  6. hdu 2686 费用流 / 双线程DP

    题意:给一个方阵,求从左上角出到右下角(并返回到起点),经过每个点一次不重复,求最大获益(走到某处获得改点数值),下来时每次只能向右或向下,反之向上或向左. 俩种解法: 1  费用流法:思路转化:从左 ...

  7. Codeforces 667D World Tour【最短路+枚举】

    垃圾csdn,累感不爱! 题目链接: http://codeforces.com/contest/667/problem/D 题意: 在有向图中找到四个点,使得这些点之间的最短距离之和最大. 分析: ...

  8. 详解DNS,你真的懂吗?

    what`s  this ? 概念 域名系统(英文:DomainNameSystem,缩写:DNS)是互联网的一项服务.它作为将域名和IP地址相互映射的一个分布式数据库,能够使人更方便地访问互联网.D ...

  9. BZOJ——1720: [Usaco2006 Jan]Corral the Cows 奶牛围栏

    http://www.lydsy.com/JudgeOnline/problem.php?id=1720 Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 1 ...

  10. Codeforces 123 E Maze

    Discription A maze is represented by a tree (an undirected graph, where exactly one way exists betwe ...