$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 ;
}
随机推荐
- @hdu - 6594@ Double Tree
目录 @description@ @solution@ @accepted code@ @details@ @description@ 给定两棵 N 个点的树,以及树上每条边的权值 w(u, v),每 ...
- 关于react-router 路径改变页面没有刷新
routert.js 中: <Router> <Switch> <Route exact path="/" component={Login}> ...
- Wood Processing牛客第十场 斜率优化DP
卧槽我感觉写的是对的,但是就是样例都过不了...留坑 #include<iostream> #include<stdio.h> #include<string.h> ...
- Springboot2 Logback mybatis 打印sql执行语句
把这个加入到logback.xml 中就可以打印mysql的日志了 <logger name="jdbc.sqltiming" level="debug" ...
- Educational Codeforces Round 12 B C题、
B. Shopping 题意:n个顾客,每个顾客要买m个物品,商场总共有k个物品,看hint就只知道pos(x)怎么算了,对于每一个Aij在k个物品中找到Aij的位置.然后加上这个位置对于的数值,然后 ...
- NIO 中文乱码问题的解决代码实现
之前在网上查询了很多关于解决NIO中文乱码的问题,仁者见仁智者见智,不过就找到的几种方法实现都太繁琐了,稍微研究了下NIO源码,以下是我自己的一种实现,偷懒用最简单的代码去实现是我的习惯! Demo: ...
- [转]敏捷开发需求管理(产品backlog)
传统的瀑布工作模式使用详细的需求说明书来表达需求,需求人员负责做需求调研,根据调研情况编制详细的需求说明书,进行需求评审,评审之后签字确认交给研发团队设计开发.在这样的环境下,需求文档是信息传递的主体 ...
- SQL 三个表练习(student,teacher,score)
- C#的选择语句
一.选择语句 if,else if是如果的意思,else是另外的意思,if'后面跟()括号内为判断条件,如果符合条件则进入if语句执行命令.如果不符合则不进入if语句.else后不用加条件,但是必须与 ...
- Notice: Use of undefined constant - assumed ' '
昨天看手册的时候有两个范例,懒得写了,直接复制,测试一下,结果报Notice; 反复检查无果,最后, 手动敲了一遍,居然正常了,汗.... 总结:偷懒害人