$CH5105 Cookies$ 线性$DP+$贪心

Posted forward777

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了$CH5105 Cookies$ 线性$DP+$贪心相关的知识,希望对你有一定的参考价值。

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^ig[t])$

 

最后,这题还要记录答案

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

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

 

Code

技术图片
 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<vector>
 5 #include<algorithm>
 6 #define Rg register
 7 #define il inline
 8 #define db double
 9 #define ll long long
10 #define inf 2100000000
11 #define go(i,a,b) for(Rg int i=a;i<=b;++i)
12 #define yes(i,a,b) for(Rg int i=a;i>=b;--i)
13 using namespace std;
14 il int read()
15 
16     int x=0,y=1;char c=getchar();
17     while(c<0||c>9)if(c==-)y=-1;c=getchar();
18     while(c>=0&&c<=9)x=(x<<3)+(x<<1)+c-0;c=getchar();
19     return x*y;
20 
21 struct nodeint dat,pos;g[31];
22 struct node1int i,j;a[31][5001];
23 il bool cmp(node x,node y)return x.dat>y.dat;
24 int n,m,ans[31],f[31][5001];
25 int main()
26 
27     n=read(),m=read();
28     go(i,0,n)go(j,0,m)f[i][j]=inf;f[0][0]=0;
29     go(i,1,n)g[i].dat=read(),g[i].pos=i;
30     sort(g+1,g+n+1,cmp);
31     go(i,2,n)g[i].dat+=g[i-1].dat;
32     go(i,1,n)
33         go(j,i,m)
34     
35         f[i][j]=f[i][j-i];a[i][j]=(node1)i,j-i;
36         go(k,1,i)
37             if(f[i][j]>f[k-1][j-(i-k+1)]+(k-1)*(g[i].dat-g[k-1].dat))
38                f[i][j]=f[k-1][j-(i-k+1)]+(k-1)*(g[i].dat-g[k-1].dat),a[i][j]=(node1)k-1,j-(i-k+1);
39     
40     int t1=n,t2=m;
41     while(t1)
42     
43         if(t1==a[t1][t2].i)go(i,1,t1)ans[g[i].pos]++;
44         elsego(i,a[t1][t2].i+1,t1)ans[g[i].pos]++;
45         int tt=t1;t1=a[t1][t2].i;t2=a[tt][t2].j;
46     
47     printf("%d\n",f[n][m]);
48     go(i,1,n)printf("%d ",ans[i]);
49     return 0;
50 
View Code

 

以上是关于$CH5105 Cookies$ 线性$DP+$贪心的主要内容,如果未能解决你的问题,请参考以下文章

CH5105cookies 贪心+DP

《算法竞赛进阶指南》0x51线性DP Cookies

数位dp,贪心,线性dp复习总结

CH5101 LCIS线性dp

CH5102 Mobile Service线性dp

CH5103 传纸条线性dp