dp优化

入口

A(fzu 1894)

  普通的单调队列,trick是进队判断的符号选取(>=wa , >ac).

B(poj 2823)

  没什么好说的 ,坑爹poj   g++,tle ;c++,ac.

C(hdu 3415)

  尝试封装了一下单调队列。。。感觉也没有方便多少.

 1 #define maxn 100010

 2 #define INF 1000000000

 3 int a[maxn<<1],p[maxn<<1],n,k;

 4 

 5 struct Que

 6 {

 7     int q[maxn<<1],front,tail,cmp;

 8     void clear()    {front = tail = 0;}

 9     void ins(int id)

10     {

11         while (front<tail && a[id]*cmp>a[q[tail-1]]*cmp)    tail--;

12         q[tail++] = id;

13     }

14     void keep(int range)

15     {

16         while (front<tail && q[tail-1]-q[front]>=range)    front++;

17     }

18     int query(int id)    {    return q[id];    }

19 };Que q;

20 void input()

21 {

22     int i;

23     scanf("%d%d",&n,&k);

24     for ( i=1 ; i<=n ; i++ )

25     {

26         scanf("%d",&a[i]);

27         a[i+n] = a[i];    p[i] = i;    p[i+n] = p[i];

28     }

29     for ( i=1 ; i<=2*n ; i++ ) a[i] = a[i-1]+a[i];

30 }

31 void solv()

32 {

33     int i,l,r,sum;

34     l = r = sum = -INF;

35     q.clear();

36     q.cmp = -1;

37     for ( i=0 ; i<2*n ; i++ )

38     {

39         q.ins(i);

40         q.keep(k);

41         if (a[i+1]-a[q.query(q.front)] > sum)

42         {

43             l = p[q.query(q.front)]+1;

44             r = p[i+1];

45             sum = a[i+1]-a[q.query(q.front)];

46         }else if (a[i+1]-a[q.query(q.front)] == sum)

47         {

48             if (p[q.query(q.front)]+1<l)

49             {

50                 l = p[q.query(q.front)]+1;

51                 r = p[i+1];

52             }else if (p[q.query(q.front)]+1==l && p[i+1]<r)    r=p[i+1];

53         }

54     }

55     printf("%d %d %d\n",sum,l,r);

56 }

57 int main()

58 {

59     int cas;

60     scanf("%d",&cas);

61     while (cas--)

62     {

63         input();

64         solv();

65     }

66     return 0;

67 }
View Code

D(hdu 3401)

  先列出朴素的dp方程逐渐,分析出可以优化的地方:

  递推优化:  dp[i][j] = max(dp[i][j],dp[i-1][j]);

  单调队列优化:  dp[i][j] = max{  dp[i][j]  ,  dp[i-w-1][q.head]+(j-q.head)*num  };

  trick是前w+1天不能进行买卖,要特判并跳过买卖的决策.

 1 #include <cmath>

 2 #include <ctime>

 3 #include <queue>

 4 #include <cstdio>

 5 #include <string>

 6 #include <cstring>

 7 #include <iostream>

 8 #include <algorithm>

 9 using namespace std;

10 #define maxn 2020

11 #define INF 1000000000

12 int ap[maxn],bp[maxn],as[maxn],bs[maxn],t,maxp,w,dp[maxn][maxn];

13 void input()

14 {

15     int i;

16     scanf("%d%d%d",&t,&maxp,&w);

17     for ( i=1 ; i<=t ; i++ )    scanf("%d%d%d%d",&ap[i],&bp[i],&as[i],&bs[i]);

18 }

19 int q[maxn],front,tail;

20 void DP()

21 {

22     int i,j,k;

23     for ( i=1,dp[0][0]=0 ; i<=maxp ; i++ )    dp[0][i] = -INF;

24     for ( i=1 ; i<=t ; i++ )

25     for ( j=0 ; j<=maxp ; j++ )

26     {

27         if (j<=as[i])    dp[i][j] = -ap[i]*j;

28         else    dp[i][j] = -INF;

29     }

30     for ( i=1 ; i<=t ; i++ )

31     {

32         for ( j=0 ; j<=maxp ; j++ )    dp[i][j] = max(dp[i][j],dp[i-1][j]);

33         if ((k=i-w-1)<0)    continue;

34 

35         front = tail = 0;

36         //    buy

37         for ( j=0 ; j<=maxp ; j++ )

38         {

39             while (front<tail && j-q[front]>as[i])    front++;

40             while (front<tail && dp[k][j]+j*ap[i]>=dp[k][q[tail-1]]+q[tail-1]*ap[i])    tail--;

41             q[tail++] = j;

42             int tmp = dp[k][q[front]]-(j-q[front])*ap[i];

43         //    printf("dp[%d][%d] = max:    %d    ,    dp[%d][%d]-(%d-%d)*%d = %d\n",i,j,dp[i][j],k,q[front],j,q[front],ap[i],max(dp[i][j],tmp));

44             dp[i][j] = max(dp[i][j],tmp);

45         }

46 

47         front = tail = 0;

48         //    sell

49         for ( j=maxp ; j>=0 ; j-- )

50         {

51             while (front<tail && q[front]-j>bs[i])    front++;

52             while (front<tail && dp[k][j]+j*bp[i]>=dp[k][q[tail-1]]+q[tail-1]*bp[i])    tail--;

53             q[tail++] = j;

54             int tmp = dp[k][q[front]]-(j-q[front])*bp[i];

55         //    printf("dp[%d][%d] = max:    %d    ,    dp[%d][%d]-(%d-%d)*%d = %d\n",i,j,dp[i][j],k,q[front],j,q[front],bp[i],max(dp[i][j],tmp));

56             dp[i][j] = max(dp[i][j],tmp);

57         }

58     }

59     int ans=-INF;

60     for ( i=0 ; i<=t ; i++ )

61     for ( j=0 ; j<=maxp ; j++ )    ans = max(ans,dp[i][j]);

62     printf("%d\n",ans);

63 }

64 int main()

65 {

66     int cas;

67     scanf("%d",&cas);

68     while (cas--)

69     {

70         input();

71         DP();

72     }

73     return 0;

74 }
View Code

 

E(hdu 3530)

  关键是求区间给定区间的最大值和最小值,有很多办法,在此题中,可以用单调队列做到O(n).

  trick:  当最大-最小>k时需要删除队列元素维护,但是当小于m时不用进行删除操作,因为没用。。。

 1 #include <cmath>

 2 #include <ctime>

 3 #include <queue>

 4 #include <cstdio>

 5 #include <string>

 6 #include <cstring>

 7 #include <iostream>

 8 #include <algorithm>

 9 using namespace std;

10 #define maxn 1000100

11 int n,m,k,a[maxn];

12 int qs[maxn],ts,fs,ql[maxn],tl,fl,q[maxn],front,tail;

13 bool inq[maxn];

14 void input()

15 {

16     int i;

17     for ( i=1 ; i<=n ; i++ )    scanf("%d",&a[i]);

18 }

19 int queryl()

20 {

21     while (fl<tl && !inq[ql[fl]])    fl++;

22     return a[ql[fl]];

23 }

24 int querys()

25 {

26     while (fs<ts && !inq[qs[fs]])    fs++;

27     return a[qs[fs]];

28 }

29 void solv()

30 {

31     int i,ans=0;

32     front = tail = fs = ts = fl = tl = 0;

33     for ( i=1 ; i<=n ; i++ )

34     {

35         q[tail++] = i;

36         inq[i] = 1;

37         while (fs<ts && a[i]<a[qs[ts-1]])    ts--;

38         qs[ts++] = i;

39         while (fl<tl && a[i]>a[ql[tl-1]])    tl--;

40         ql[tl++] = i;

41         while(front<tail && queryl()-querys()>k)

42         {

43             inq[q[front]] = 0;

44             front++;

45         }

46         if (queryl()-querys()>=m && queryl()-querys()<=k)    ans = max(ans,q[tail-1]-q[front]+1);

47     }

48     printf("%d\n",ans);

49 }

50 int main()

51 {

52     while (scanf("%d%d%d",&n,&m,&k)!=EOF)

53     {

54         input();

55         solv();

56     }

57     return 0;

58 }
View Code

 

F(poj3017)

  非常有启发性的一题:利用线段树的单点更新更新单调队列里面的值.单调队列保证了快速获得区间最值,线段树的区间查询保证了答案的最优性.

 1 #include <cmath>

 2 #include <ctime>

 3 #include <queue>

 4 #include <cstdio>

 5 #include <string>

 6 #include <cstring>

 7 #include <iostream>

 8 #include <algorithm>

 9 using namespace std;

10 typedef long long llong;

11 const llong INF = 1ll<<60;

12 #define maxn 100100

13 #define ls (rt<<1)

14 #define rs (rt<<1|1)

15 #define mid ((l+r)>>1)

16 struct node

17 {

18     int l,r,big;

19 };node q[maxn];

20 llong tree[maxn<<2],m,dp[maxn];

21 int a[maxn],n,front,tail;

22 void buildtree(int l,int r,int rt)

23 {

24     tree[rt] = INF;

25     if (l == r)    return;

26     buildtree(l,mid,ls);

27     buildtree(mid+1,r,rs);

28 }

29 void pushup(int rt)

30 {

31     tree[rt] = min(tree[ls],tree[rs]);

32 }

33 void ins(llong var,int pos,int l,int r,int rt)

34 {

35     if (l == r)

36     {

37         tree[rt] = var;

38         return;

39     }

40     if (pos<=mid)    ins(var,pos,l,mid,ls);

41     else    ins(var,pos,mid+1,r,rs);

42     pushup(rt);

43 }

44 llong query(int L,int R,int l,int r,int rt)

45 {

46     llong res1,res2;

47     res1 = res2 = INF;

48     if (L<=l && r<=R)    return tree[rt];

49     if (L<=mid)    res1 = query(L,R,l,mid,ls);

50     if (R>mid)    res2 = query(L,R,mid+1,r,rs);

51     return min(res1,res2);

52 }

53 llong solv()

54 {

55     int i,lft;

56     llong cnt=0;

57     node tmp;

58     buildtree(0,n,1);

59     front = tail = 0;

60     for ( i=1 ; i<=n ; i++ )

61     if (a[i]>m)    return -1;

62     for ( lft=i=1,dp[0]=0 ; i<=n ; i++ )

63     {

64         cnt += a[i];

65         while (cnt>m)

66         {

67             q[front].l++;

68             if (q[front].l>q[front].r)

69             {

70                 ins(INF,front,0,n,1);

71                 front++;

72             }else    ins(dp[q[front].l-1]+q[front].big,front,0,n,1);

73             cnt -= a[lft++];

74         }

75         tmp.l = tmp.r = i;    tmp.big = a[i];

76         while (front<tail && tmp.big>=q[tail-1].big)

77         {

78             tmp.l = q[tail-1].l;    //merge

79             ins(INF,tail-1,0,n,1);

80             tail--;

81         }

82         q[tail++] = tmp;

83         ins(dp[q[tail-1].l-1]+q[tail-1].big,tail-1,0,n,1);

84         dp[i] = query(front,tail-1,0,n,1);

85     //    printf("dp[%d]=%I64d\n",i,dp[i]);

86     }

87     return dp[n];

88 }

89 int main()

90 {

91     while (scanf("%d%I64d",&n,&m)!=EOF)

92     {

93         for (int i=1 ; i<=n ; i++ ) scanf("%d",&a[i]);

94         printf("%I64d\n",solv());

95     }

96     return 0;

97 }
View Code

G(poj3245)

  为了满足 " 当p<q 时 , Bp > Aq " 的条件,需要先将数据预处理成块状, 即 对所有p ,要找到最大的q 使得 B<= Aq  .

  这是第一步,朴素做法O(n^2) ,  用一点技巧可以做到nlogn :  线段树(比较麻烦,可能要离散化,代码量大) 或者 分别对A和对B降序排序O(nlogn) ,再用2个指针扫描 O(n) , 要记得记录排序前的原始下标.

  第二步,在limt的限制下求最小sum的分组方法, 很容易想到要二分答案.

    第三步,对于二分的sum值,需要一个验证办法.注意,让每组尽量接近sum的贪心分组办法是错的, 因为这里还要考虑到 ΣMi 的限制.

  老老实实dp:

  dp[i]表示以第i个为结尾, ΣM 最小的分组方法.

  dp[i] = min {dp[j] + max{aj+1,...,ai} }.

  这个方程和F题的非常相似,把决策存在单调队列里,用线段树得到最优值.

  1 #include <cmath>

  2 #include <ctime>

  3 #include <queue>

  4 #include <cstdio>

  5 #include <string>

  6 #include <cstring>

  7 #include <iostream>

  8 #include <algorithm>

  9 using namespace std;

 10 typedef long long llong;

 11 #define maxn 50100

 12 #define ls (rt<<1)

 13 #define rs ((rt<<1)+1)

 14 #define mid ((l+r)>>1)

 15 #define BIG 1

 16 #define SML 0

 17 #define INF (1ll<<31)

 18 struct node

 19 {

 20     int a,b,id;

 21 };node p[maxn],sa[maxn],sb[maxn],e[maxn];

 22 llong init[2];

 23 llong sumb[maxn],tree[maxn<<2];

 24 int n,lmt,cnte,lst[maxn];

 25 

 26 bool cmpa(const node& u,const node& v)    { return u.a>v.a; }

 27 bool cmpb(const node& u,const node& v)    { return u.b>v.b; }

 28 llong query_big(int L,int R,int l,int r,int rt)

 29 {

 30     llong resl,resr;

 31     resl = resr = init[BIG];

 32     if (L<=l && r<=R)    return tree[rt];

 33     if (L<=mid)    resl = query_big(L,R,l,mid,ls);

 34     if (R>mid)    resr = query_big(L,R,mid+1,r,rs);

 35     return max(resl,resr);

 36 }

 37 llong query_sml(int L,int R,int l,int r,int rt)

 38 {

 39     llong resl,resr;

 40     resl = resr = init[SML];

 41     if (L<=l && r<=R)    return tree[rt];

 42     if (L<=mid)    resl = query_sml(L,R,l,mid,ls);

 43     if (R>mid)    resr = query_sml(L,R,mid+1,r,rs);

 44     return min(resl,resr);

 45 }

 46 void buildtree(int l,int r,int rt,int flg)

 47 {

 48     tree[rt] = init[flg];

 49     if (l==r)    return;

 50     buildtree(l,mid,ls,flg);

 51     buildtree(mid+1,r,rs,flg);

 52 }

 53 void pushup(int rt,int flg)

 54 {

 55     if (flg==BIG)    tree[rt] = max(tree[ls],tree[rs]);

 56     else    tree[rt] = min(tree[rs],tree[ls]);

 57 }

 58 void ins(int val,int pos,int l,int r,int rt,int flg)

 59 {

 60     if (l==r)    { tree[rt]=val; return; }

 61     if (pos<=mid)    ins(val,pos,l,mid,ls,flg);

 62     else    ins(val,pos,mid+1,r,rs,flg);

 63     pushup(rt,flg);

 64 }

 65 void pretreat()

 66 {

 67     int i,j,k;

 68     buildtree(1,n,1,BIG);

 69     for ( i=1 ;i<=n ; i++ )    sa[i]=p[i],    sb[i]=p[i];

 70     sort(sa+1,sa+1+n,cmpa);    sort(sb+1,sb+1+n,cmpb);

 71 //    for ( i=1 ; i<=n ; i++ ) printf("sa: a=%d id=%d\nsb: b=%d id=%d\n\n",sa[i].a,sa[i].id,sb[i].b,sb[i].id);

 72     for ( i=j=1,k=0 ; i<=n ; i++ )

 73     {

 74         lst[ sb[i].id ] = sb[i].id;

 75         while (j<=n && sa[j].a>=sb[i].b) k=max(k,sa[j].id),j++;

 76         lst[ sb[i].id ] = max(sb[i].id,k);

 77         ins(lst[ sb[i].id ],sb[i].id,1,n,1,BIG);

 78     }

 79     for ( i=1 ; i<=n ; i++ )

 80         lst[i] = query_big(i,lst[i],1,n,1);

 81     buildtree(1,n,1,BIG);

 82     for ( i=1 ; i<=n ; i++ ) sumb[i] = sumb[i-1] + p[i].b;

 83     for ( i=1 ; i<=n ; i++ )    ins(p[i].a,i,1,n,1,BIG);

 84     for ( i=1,cnte=0 ; i<=n ; i++ )

 85     {

 86         e[++cnte].a = query_big(i,lst[i],1,n,1);

 87         e[cnte].b = sumb[lst[i]] - sumb[i-1];

 88         e[cnte].id = cnte;

 89         i = lst[i];

 90     }

 91 //    for ( i=1 ; i<=cnte ; i++ ) printf("e[%d]: a=%d b=%d\n",i,e[i].a,e[i].b);

 92     for ( i=1 ; i<=cnte ; i++ )    sumb[i] = sumb[i-1] + e[i].b;

 93 }

 94 struct node2

 95 {

 96     int l,r,big;

 97 };node2 q[maxn];

 98 

 99 int front,tail;

100 llong dp[maxn];

101 int check(int sum)

102 {

103     int i,lft;

104     llong cnt=0;

105     node2 tmp;

106 

107     front = tail = 0;

108     for ( i=1 ; i<=cnte ; i++ ) if (e[i].b>sum)    return 0;

109 

110     for ( i=lft=1 ; i<=cnte ; i++ )

111     {

112         cnt += e[i].b;

113         while (cnt>sum)

114         {

115             q[front].l++;

116             if (q[front].l>q[front].r)

117             {

118                 ins(init[SML],front,0,n,1,SML);

119                 front++;

120             }else    ins(dp[q[front].l-1]+q[front].big,front,0,n,1,SML);

121             cnt -= e[lft++].b;

122         }

123         tmp.l = tmp.r = i;    tmp.big = e[i].a;

124         while (front<tail && tmp.big>=q[tail-1].big)

125         {

126             tmp.l = q[tail-1].l;

127             ins(init[SML],tail-1,0,n,1,SML);

128             tail--;

129         }

130         q[tail++] = tmp;

131         ins(dp[tmp.l-1]+tmp.big,tail-1,0,n,1,SML);

132         dp[i] = query_sml(front,tail-1,0,n,1);

133     }

134     if (dp[cnte]<=lmt)    return 1;

135     else    return 0;

136 }

137 int solv()

138 {

139     int l,r;

140     l = 0;    r = sumb[n];

141     while (l<r)

142     {

143         if (check(mid))    r=mid;

144         else    l=mid+1;

145     }    return r;

146 }

147 int main()

148 {

149     init[BIG] = 0;    init[SML] = INF;

150     scanf("%d%d",&n,&lmt);

151     for (int i=1 ; i<=n ; i++ ) {    scanf("%d%d",&p[i].a,&p[i].b);    p[i].id=i;    }

152     pretreat();

153     int ans = solv();

154     printf("%d\n",ans);

155     return 0;

156 }
View Code

斜率优化dp:

H(hdu 2993)

 1 #include <cmath>

 2 #include <ctime>

 3 #include <queue>

 4 #include <cstdio>

 5 #include <string>

 6 #include <cstring>

 7 #include <iostream>

 8 #include <algorithm>

 9 using namespace std;

10 typedef long long llong;

11 #define maxn 100100

12 #define ls (rt<<1)

13 #define rs ((rt<<1)+1)

14 #define mid ((l+r)<<1)

15 int sum[maxn];

16 int n,m;

17 int q[maxn],front,tail;

18 

19 double g(int a,int b)

20 {

21     double res = (double)(sum[b]-sum[a-1])/(double)(b-a+1.0);

22     return res;

23 }

24 void solv()

25 {

26     int i;

27     double ans=0;

28     front = tail = 0;

29     for ( i=m ; i<=n ; i++ )

30     {

31         while (front+1<tail && g(q[tail-2],q[tail-1])>g(q[tail-1],i-m+1))    tail--;

32         q[tail++] = i-m+1;

33         while (front+1<tail && g(q[front],i)<=g(q[front+1],i)) front++;

34         ans = max(ans,g(q[front],i));

35     }

36     printf("%.2lf\n",ans);

37 }

38 int GetInt()

39 {

40     char ch=getchar();

41     while(ch<'0'||ch>'9')ch=getchar();

42     int num=0;

43     while(ch>='0'&&ch<='9'){

44         num=num*10+ch-'0';

45         ch=getchar();

46     }

47     return num;

48 }

49 int main()

50 {

51     while (scanf("%d%d",&n,&m)!=EOF)

52     {

53         for (int i=1 ; i<=n ; i++ )

54         {

55             sum[i] = GetInt();

56             sum[i] += sum[i-1];

57         }

58         solv();

59     }

60     return 0;

61 }
View Code

I(hdu 2829)

 1 #include <cmath>

 2 #include <ctime>

 3 #include <queue>

 4 #include <cstdio>

 5 #include <string>

 6 #include <cstring>

 7 #include <iostream>

 8 #include <algorithm>

 9 using namespace std;

10 #define maxn 1010

11 typedef long long llong;

12 #define ls (rt<<1)

13 #define rs ((rt<<1)+1)

14 #define mid ((l+r)<<1)

15 const llong INF = 1ll<<62;

16 llong dp[maxn][maxn],v[maxn],sum[maxn];

17 int n,m,a[maxn];

18 

19 void init()

20 {

21     int i;

22     for ( i=1 ; i<=n ; i++ ) sum[i] = sum[i-1]+a[i];

23     for ( i=1 ; i<=n ; i++ ) v[i] = v[i-1]+sum[i-1]*a[i];

24 }

25 int q[maxn],front,tail;

26 

27 llong w(int j,int i)

28 {

29     return v[i]-v[j]-sum[j]*(sum[i]-sum[j]);

30 }

31 int x;

32 double g(int id,int a,int b)

33 {

34     double xa,xb,ya,yb;

35     ya = dp[id][a] - v[a]+sum[a]*sum[a];    xa = sum[a];

36     yb = dp[id][b] - v[b]+sum[b]*sum[b];    xb = sum[b];

37     return (ya-yb) / (xa-xb);

38 }

39 void DP()

40 {

41     int i,j;

42     for ( i=0 ; i<=n ; i++ ) dp[0][i] = v[i];

43 //    for ( i=0 ; i<=n ; i++ ) printf("dp[0][%d]=%I64d\n",i,dp[0][i]);    printf("\n");

44 

45     for ( i=1 ; i<=m ; i++ )

46     {

47         front = tail = 0;

48         q[tail++] = i;

49         for ( j=i+1 ; j<=n ; j++ )

50         {

51             x = j;

52             while (front+1<tail && g(i-1,q[front],q[front+1])<=(double)sum[j])    front++;

53             dp[i][j] = dp[i-1][q[front]] + w(q[front],j);

54     //        printf("dp[%d][%d] = %I64d        q[front]=%d\n",i,j,dp[i][j],q[front]);

55             while (front+1<tail && g(i-1,q[tail-2],q[tail-1])>=g(i-1,q[tail-1],j))    tail--;

56             q[tail++] = j;

57         }

58     }

59     llong res=INF;

60     for ( i=0 ; i<=m ; i++ )    res = min(res,dp[i][n]);

61     cout<<res<<endl;

62 }

63 int main()

64 {

65     while (scanf("%d%d",&n,&m)!=EOF)

66     {

67         if (!n && !m)    break;

68         for (int i=1 ; i<=n ; i++ ) scanf("%d",&a[i]);

69         init();

70         DP();

71     }

72     return 0;

73 }
View Code

J(hdu 3507)

 1 #include <cstdio>

 2 #include <cstring>

 3 #include <algorithm>

 4 #include <iostream>

 5 #include <queue>

 6 #include <vector>

 7 using namespace std;

 8 typedef long long llong;

 9 #define maxn 600010

10 llong dp[maxn],sum[maxn];

11 int a[maxn],n,m,q[maxn],front,tail;

12 

13 double dx(int a,int b){return (double)(sum[a]-sum[b]);}

14 double dy(int a,int b){return (double)(dp[a]+sum[a]*sum[a]-dp[b]-sum[b]*sum[b]);}

15 int check(int a,int b,llong c)

16 {

17     llong resa = dp[a] + (sum[a]-c)*(sum[a]-c);

18     llong resb = dp[b] + (sum[b]-c)*(sum[b]-c);

19     if (resa>resb)    return 1;

20     else    return 0;

21 }

22 void solv()

23 {

24     int i;

25     for ( i=1 ; i<=n ; i++ ) sum[i] = sum[i-1] + a[i];

26     front = tail = 0;

27     q[tail++] = 0;

28     for ( i=1 ; i<=n ; i++ )

29     {

30         while (front+1<tail && check(q[front],q[front+1],sum[i])) front++;

31         dp[i] = dp[q[front]] + (sum[i]-sum[q[front]]) * (sum[i]-sum[q[front]])+m;

32    //     printf("dp[%d] = %lld\n",i,dp[i]);

33         while (front+1<tail && dy(q[tail-1],q[tail-2]) * dx(i,q[tail-1]) >= dx(q[tail-1],q[tail-2]) * dy(i,q[tail-1])) tail--;

34         q[tail++] = i;

35     }

36     cout<<dp[n]<<endl;

37 }

38 int main()

39 {

40     while (scanf("%d%d",&n,&m)!=EOF)

41     {

42         for (int i=1 ; i<=n ; i++ ) scanf("%d",&a[i]);

43         solv();

44     }

45     return 0;

46 }
View Code

  I,J需要比较决策得到斜率形式,比较决策的形式:

    i<j<k 时  g(i,j)<常数c可推出j更优 ,g(i,j)<g(j,k)<常数c 可推出决策j不会为最优可从集合中去掉

  H不需要比较决策直接是斜率形式.

   设i<j<k , g(i,j)>g(j,k) 可以通过图像知道上凸点j不会成为最优决策.

你可能感兴趣的:(优化)