zoukankan      html  css  js  c++  java
  • hdu 3669 Cross the Wall(斜率优化DP)

    题目连接:hdu 3669 Cross the Wall

    题意:

    现在有一面无限大的墙,现在有n个人,每个人都能看成一个矩形,宽是w,高是h,现在这n个人要通过这面墙,现在只能让你挖k个洞,每个洞不能重叠,每个洞需要消耗你挖的w*h,现在问你最小消耗多少。

    题解:

    设dp[i][j]为前j个人挖i个洞的最小消耗。

    首先我们先将每个人按w排序,我们可以发现,排序后的h是递减的,因为如果不是递减的,可以把那个点消掉,因为w[k]<w[j]&&h[k]<h[j]的话,那么第k个人就可以直接过第j个人的洞。

    然后我们可以预处理一下。

    然后可以得

    dp[i][j]=min{dp[i-1][k]+w[j]*h[k+1]}(k<j)

    然后考虑斜率优化

    设k>l,对于dp[i][j],第k个人到第j个人通过一个洞比第l个人到第j个人通过一个洞更优

    有dp[i-1][k]+w[j]*h[k+1]<=dp[i-1][l]+w[j]*h[l+1];

    整理得

    dp[i-1][k]-dp[i-1][l]/h[l+1]-h[k+1]<=w[j];

    然后单调队列优化一下就好。

     1 #include<bits/stdc++.h>
     2 #define F(i,a,b) for(int i=a;i<=b;++i)
     3 using namespace std;
     4 typedef long long ll;
     5 
     6 const int N=5e4+7;
     7 int n,k,Q[N],ed;
     8 ll dp[101][N],ans,inf=1ll<<60;
     9 struct node
    10 {
    11     ll w,h;
    12     bool operator < (const node &b)const{return w<b.w;}
    13 }a[N],b[N];
    14 
    15 ll getx(int k,int l){return -b[k+1].h+b[l+1].h;}
    16 ll gety(int i,int k,int l){return dp[i][k]-dp[i][l];}
    17 ll check(int i,int j,int k,int l){return gety(i,j,k)*getx(k,l)<=gety(i,k,l)*getx(j,k);}
    18 
    19 int main()
    20 {
    21     while(~scanf("%d%d",&n,&k))
    22     {
    23         F(i,1,n)scanf("%lld%lld",&a[i].w,&a[i].h);
    24         sort(a+1,a+1+n),ed=0;
    25         F(i,1,n)
    26         {
    27             while(ed&&a[i].h>b[ed].h)ed--;
    28             b[++ed]=a[i];
    29         }
    30         F(i,1,ed)dp[1][i]=b[i].w*b[1].h;
    31         F(i,2,k)
    32         {
    33             int head=1,tail=0;
    34             Q[++tail]=i-1;
    35             F(j,i,ed)
    36             {
    37                 while(head<tail&&gety(i-1,Q[head+1],Q[head])<=b[j].w*getx(Q[head+1],Q[head]))head++;
    38                 dp[i][j]=dp[i-1][Q[head]]+b[j].w*b[Q[head]+1].h;
    39                 while(head<tail&&check(i-1,j,Q[tail],Q[tail-1]))tail--;
    40                 Q[++tail]=j;
    41             }
    42         }
    43         ans=inf;
    44         F(i,1,k)if(ans>dp[i][ed])ans=dp[i][ed];
    45         printf("%lld
    ",ans);
    46     }
    47     return 0;
    48 }
    View Code
  • 相关阅读:
    在线预览Office文档
    花生壳内网穿透
    Net core跨域
    EF链表查询
    Python冒泡排序、选择排序、插入排序、希尔排序、归并排序
    竟然可以这样学python!
    如何使用python打印9乘9乘法口诀表?
    python爬取小视频
    —用python写PDF转换器
    从0到1搭建个人博客-Django(三)
  • 原文地址:https://www.cnblogs.com/bin-gege/p/6152844.html
Copyright © 2011-2022 走看看