码迷,mamicode.com
首页 > 其他好文 > 详细

一种神奇的DP思想

时间:2014-10-07 22:20:34      阅读:254      评论:0      收藏:0      [点我收藏+]

标签:style   blog   color   io   os   ar   for   sp   div   

  最近考了个叫做NOIP模拟的题。。。。。

  真是难以吐槽。NOIP怎么考到了自动机去了。。。。。

  当然,想我这种蒟蒻就只能膜拜机房里的各位大牛了。。。。

  不管怎么说,我们来看一下这道很厉害的DP。

  题目大意:

  给定 N 个数, 请你将他们分成两组, 并使得两组的代价和最少

  (每一组的代价定义为 ∑¦Hpi-1 - Hpi¦, pi-1 < pi

  我考场上只想到了 20 分的DP:令 f[i][j][k]  表示 考虑前 i 个 两组结尾分别为 j , k  时的最优值。

  考试后,大牛就给了我一个 50 分算法:f[i][j] 表示 第一列以 i 结尾, 第二列以 j 结尾的最优值。(强制令 i > j)

  那么很明显 f[i][j] -> f[i+1][i]  或 f[i+1][j]

  :-( 怎么会这样呢?

  第二天,大牛告诉我说他 AC 了, 一问才知道 他强制令 i - j <= 20 这样居然骗到了 95 分。。。(⊙o⊙)…

  

  没办法,自己怎么会有那么厉害的YY能力?

  只能看题解:

    所以说不愧是题解

    令 g[i] = f[i][i-1]

    则 g[i] = min(g[j] + sum[i-1]  - sum[j] + abs(H[i] - H[j-1])) (sum[i] = sum[i-1] + abs(Hi - Hi-1))

    那么我们对这个绝对值号进行分类讨论,那么就可以维护处最优解了。

    我们用两棵树状数组来维护这个值 (即 g[j] - sum[j] ± H[j-1])

    我们先将 H[i] 离散化, 那么对于 H[i] > H[j] 查找的范围为 树状数组A [1 , i)

                               否则为 树状数组B (i, n]

    代码就是这个样子的:

    

 1 #include<cstdlib>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cstring>
 5 #define maxn 500500
 6 using namespace std;
 7 long long n,h[maxn];
 8 long long sum[maxn];
 9 long long Bit1[maxn],Bit2[maxn];
10 long long f[maxn];
11 long long ans,a[maxn],tot;
12 int lowbit(int x)
13 {
14     return x & (-x);
15 }
16 void change(long long bit[],int pos,long long x)
17 {
18     while(pos <= n){
19         bit[pos] = min(bit[pos],x);
20         pos += lowbit(pos);
21     }
22 }
23 long long ask(long long bit[],int pos)
24 {
25     long long ret = 0x7fffffffff;
26     while(pos){
27         ret = min(ret,bit[pos]);
28         pos -= lowbit(pos);
29     }
30     return ret;
31 }
32 int main()
33 {
34     freopen("sprung.in","r",stdin);
35     freopen("sprung.out","w",stdout);
36     scanf("%I64d",&n);
37     memset(Bit1,0x3f,sizeof(Bit1));
38     memset(Bit2,0x3f,sizeof(Bit2));
39     f[0] = 0;
40     ans = 0x7ffffffff;
41     for(int i=1;i<=n;++i) scanf("%I64d",&h[i]),a[i] = h[i];
42     sort(a+1,a+n+1); tot = unique(a+1,a+n+1) - a;
43     for(int i=1;i<=n;++i) sum[i] = sum[i-1] + abs(h[i] - h[i-1]);
44     change(Bit1,1,0);
45     change(Bit2,tot,0);
46     for(int i=2;i<=n;++i){
47         int pos = lower_bound(a+1,a+tot,h[i]) - a + 1;
48         long long x1 = ask(Bit1,pos) + h[i] ;
49         long long x2 = ask(Bit2,tot - pos + 1) - h[i];
50         f[i] = min(x1,x2) + sum[i-1];
51         ans = min(ans,f[i] + sum[n] -sum[i]);
52         pos = lower_bound(a+1,a+tot,h[i-1]) - a + 1;
53         change(Bit1,pos,f[i] - sum[i] - h[i-1]);
54         change(Bit2,tot - pos + 1,f[i] - sum[i] + h[i-1]);
55     }
56     printf("%I64d",ans);
57     return 0;    
58 }

 

 

    

 

一种神奇的DP思想

标签:style   blog   color   io   os   ar   for   sp   div   

原文地址:http://www.cnblogs.com/RHX-LMY/p/4009762.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!