$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 ;
}
随机推荐
- JVM参数详细列表
-client :设置JVM使用client模式,特点启动较快(神机不明显(I5/8G/SSD)) -server :设置JVM使用server模式.64位JDK默认启动该模式 -agentlib:l ...
- H3C路由器Telnet服务配置命令
- @NOI模拟2017.06.30 - T3@ Right
目录 @description@ @solution@ @part - 1@ @part - 2@ @accepted code@ @details@ @description@ JOHNKRAM 和 ...
- SQL 变量,运算符
一.变量 SQL语言也跟其他编程语言一样,拥有变量.分支.循环等控制语句. 在SQL语言里面把变量分为局部变量和全局变量,全局变量又称系统变量. (一).局部变量 使用declare关键字给变量声明, ...
- java基本数据类型转换之向上转型和向下转换
向上转换: 整型,字符型,浮点型的数据在混合运算中相互转换,转换时遵循以下原则: 容量小的类型可自动转换为容量大的数据类型: byte,short,char → int → long → float ...
- python组件之wtforms
简介 帮助我们在HTML中快速生成form标签,同时还可以对用户提交的form请求的数据进行验证. 安装 pip3 install wtforms 使用 创建对象:构建form标签 class Log ...
- Python--day24--复习
- HDU 5974"A Simple Math Problem"(GCD(a,b) = GCD(a+b,ab) = 1)
传送门 •题意 已知 $a,b$,求满足 $x+y=a\ ,\ LCM(x,y)=b$ 条件的 $x,y$: 其中,$a,b$ 为正整数,$x,y$ 为整数: •题解 关键式子:设 $a,b$ 为正整 ...
- H3C PPP会话建立过程
- nginx调用PHP有sock方式和端口方式
nginx调用PHP有sock方式和端口方式 1.确认nginx已经调用了php;2.先确认你的nginx使用什么方式调用PHP:3.如果使用端口方式,端口对不对应,如果使用SOCK方式,那么路径对不 ...