$CH5105\ Cookies$ 线性$DP+$贪心
是很有趣的一道题 : )
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 ;
}
随机推荐
- LeetCode Weekly Contest 6
leetcode现在每周末举办比赛,这是今天上午参加的比赛的题解.题目难度不算大,两个easy,一个medium,一个hard.hard题之前接触过,所以做得比较顺利. 1. Sum of Left ...
- css设置Overflow实现隐藏滚动条的同时又可以滚动
.scroll-list ul{ white-space: nowrap; -webkit-overflow-scrolling: touch; overflow-x: auto; overflow- ...
- 2018-11-19-win10-uwp-使用-Matrix3DProjection-进行-3d-投影
title author date CreateTime categories win10 uwp 使用 Matrix3DProjection 进行 3d 投影 lindexi 2018-11-19 ...
- 实现三个div,固定左右两边的div宽为200,中间的div宽度自适应的四种方法
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...
- pytorch入坑一 | Tensor及其基本操作
由于之前的草稿都没了,现在只有重写…. 我好痛苦 本章只是对pytorch的常规操作进行一个总结,大家看过有脑子里有印象就好,知道有这么个东西,需要的时候可以再去详细的看,另外也还是需要在实战中多运用 ...
- python组件之wtforms
简介 帮助我们在HTML中快速生成form标签,同时还可以对用户提交的form请求的数据进行验证. 安装 pip3 install wtforms 使用 创建对象:构建form标签 class Log ...
- Vue 路由规则--传参数
1,query方法去获取参数 <!DOCTYPE html> <html lang="en"> <head> <meta charset= ...
- 理解java面向对象基础
1. 类和对象 一切皆对象,这可以说是面向对象的核心思想了. 类,就是具有相同性质对象的抽象. 而类的每一个具体的实例就是一个对象. 我们可以定义一个Person类,这个Person类就是所有的人的抽 ...
- MySQL高级配置
参考文章:http://www.jb51.net/article/47419.htm https://blog.csdn.net/waneto2008/article/details/52502208 ...
- Js 时间戳显示和计算时间间隔
显示时间戳 很多地方会让页面显示当前时间并实时计时功能,例:2019年5月23号 10:28::34 代码实现如下: getTime(){ var mydate = new Date(); var y ...