CH

是很有趣的一道题 : )

Sol

第一反应就是f[i][j]表示前i个小朋友分j块饼干的最小怨气值

但是一个孩子所产生的怨气值并不固定,它与其他孩子获得饼干的情况有关

这里可以用到一个贪心,就是贪婪度大的孩子应该获得尽量多的饼干

所以先按照贪婪度由大到小排序,那么获得的饼干数也会是非严格单调递减的

然而发现很还是难转移,因为这样直接转移需要前一个孩子获得的饼干数与比前一个孩子获得饼干多的孩子数

在现有的DP状态下,很难高效维护这两种信息

对状态做一个等价转化:

1.若第i个孩子获得的饼干数大于1

可以将所有的孩子获得的饼干同时减去1,它们的相对值并没有改变,所以这样所得到的答案任然是正确的

$f[i][j]=f[i][j-i]$

2.若第i个孩子获得的饼干数等于1

就要枚举k(1<=k<=i)表示在i前获得饼干数为1的第一个孩子是谁

$f[i][j]=min(f[k][j-(i-k+1)+(k-1)*\sum_{t=k}^{i}g[t])$

最后,这题还要记录答案

在DP中需要给出方案时,一般的做法是额外使用一些与DP状态大小相同的数组记录下来每个状态的最优解是从何处转移而来的.最终,在DP求出最优解后,通过一次递归,沿着记录的每一步回到初态,即可得到一条从初态到最优解的转移路径,也就是所求的具体方案.

这题的答案统计与一般的题目不太一样,要细心.

Code

 #include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<algorithm>
#define Rg register
#define il inline
#define db double
#define ll long long
#define inf 2100000000
#define go(i,a,b) for(Rg int i=a;i<=b;++i)
#define yes(i,a,b) for(Rg int i=a;i>=b;--i)
using namespace std;
il int read()
{
int x=,y=;char c=getchar();
while(c<''||c>''){if(c=='-')y=-;c=getchar();}
while(c>=''&&c<=''){x=(x<<)+(x<<)+c-'';c=getchar();}
return x*y;
}
struct node{int dat,pos;}g[];
struct node1{int i,j;}a[][];
il bool cmp(node x,node y){return x.dat>y.dat;}
int n,m,ans[],f[][];
int main()
{
n=read(),m=read();
go(i,,n)go(j,,m)f[i][j]=inf;f[][]=;
go(i,,n)g[i].dat=read(),g[i].pos=i;
sort(g+,g+n+,cmp);
go(i,,n)g[i].dat+=g[i-].dat;
go(i,,n)
go(j,i,m)
{
f[i][j]=f[i][j-i];a[i][j]=(node1){i,j-i};
go(k,,i)
if(f[i][j]>f[k-][j-(i-k+)]+(k-)*(g[i].dat-g[k-].dat))
f[i][j]=f[k-][j-(i-k+)]+(k-)*(g[i].dat-g[k-].dat),a[i][j]=(node1){k-,j-(i-k+)};
}
int t1=n,t2=m;
while(t1)
{
if(t1==a[t1][t2].i){go(i,,t1)ans[g[i].pos]++;}
else{go(i,a[t1][t2].i+,t1)ans[g[i].pos]++;}
int tt=t1;t1=a[t1][t2].i;t2=a[tt][t2].j;
}
printf("%d\n",f[n][m]);
go(i,,n)printf("%d ",ans[i]);
return ;
}

随机推荐

  1. LeetCode80 Remove Duplicates from Sorted Array II

    题目: Follow up for "Remove Duplicates":What if duplicates are allowed at most twice? (Mediu ...

  2. 20-2 orm分组和聚合以及在项目中执行的一些方法

    一  orm分组和聚合 参考:https://www.cnblogs.com/liwenzhou/p/8660826.html 1 表结构: # 第一张表 class Employee1(models ...

  3. android学习——android 常见的错误 和 解决方法

    1. Application does not specify an API level requirement! 解决方法:AndroidManifest.xml中 加入: <uses-sdk ...

  4. MyBatis-使用XML或注解的简单实例

    一.导入jar包 <dependency> <groupId>junit</groupId> <artifactId>junit</artifac ...

  5. hdu 3662 3D Convex Hull

    Problem - 3662 题意很简单,构造三维凸包,求凸包有多少个面. 代码如下: #include <cstdio> #include <iostream> #inclu ...

  6. SQLSTATE[HY000] [2002] 错误

    http://www.thinkphp.cn/topic/36194.html 使用tp框架 3.2.3 ,在windows上跑的时候没有任何问题,但是部署到linux系统和是哪个,就会报这个错,不知 ...

  7. Ubuntu16.04.3深度学习环境搭建

    依赖 pip3 install pillow 安装numpy相关sudo apt-get install python-numpy python-scipy python-matplotlib ipy ...

  8. HDU 1114 完全背包问题

    题意:有一个存钱罐,空罐时的重量是e,满罐时的重量是f,现在有n种硬币,每一种有无限个,现在给出每一种硬币的价值p和重量w,问存钱罐中最少钱,输出最小钱,否则输出... 思路:变形的完全背包问题,只是 ...

  9. Java开发之快捷键

    1.显示桌面快捷键:win+D或者右击状态栏,选择显示桌面. 2.UE编辑器:如果想把多行记录合并为一行,使用替换(Ctrl+R),查找里输入^p(代表回车换行符),替换为里什么都不填,替换位置选择所 ...

  10. 常用mime.types

    以下是从nginx配置文件mime.types中提取出的最常用的文件格式, 整理了下, 方便查看 类型 文件格式 default_type application/octet-stream - tex ...