HDU 3669 Cross the Wall (斜率优化DP)

来源:互联网 发布:知鱼之乐 编辑:程序博客网 时间:2024/06/05 09:12

先将各矩形按照w从小到大排序。

设dp[i]为考虑前i个矩形的总的最小面积。

dp[i] = min(dp[i], dp[j] + h[k]*w[i]) k为从j+1到i的高度最大的矩形。

那么这样复杂度n^3必然T。

考虑这样一个事实:将矩形排序后,考虑第i个矩形,前i-1个矩形中高度比它小的必然可以被包含于第i个矩形,我们只需要考虑排序后矩形中高度降序的矩形。

那么方程就变为dp[i] = min(dp[i], dp[j] + h[j+1]*w[i])。

然后斜率优化就完了。


我的代码:

#include<cstdio>#include<iostream>#include<cstring>#include<vector>#include<algorithm>using namespace std;typedef long long LL;const LL maxn = 50005;struct Nod{    LL w,h;    bool operator < (const Nod &z) const{        return w < z.w;    }};LL n,k,dp[105][maxn],w[maxn],h[maxn];LL q[maxn],hd,tl;vector<Nod> vec;void init(){    vec.clear();    memset(dp,63,sizeof(dp));    dp[0][0] = 0;}LL getDP(LL j,LL k,LL i){    return dp[i-1][k] + w[j]*h[k+1];}LL getUp(LL j,LL k,LL i){    return dp[i-1][k] - dp[i-1][j];}LL getDown(LL j,LL k){    return h[j+1] - h[k+1];}void solve(){    for(LL i=1;i<=k;i++){        hd = tl = 0;        q[tl++] = i-1;        for(LL j=i;j<=n;j++){            while(hd+1<tl && getUp(q[hd],q[hd+1],i)                  <= w[j]*getDown(q[hd],q[hd+1])) hd++;            dp[i][j] = getDP(j,q[hd],i);            //printf("%lld %lld %lld %lld\n",j,q[hd],i,dp[i][j]);            while(hd+1<tl && getUp(q[tl-1],j,i)*getDown(q[tl-2],q[tl-1])                  <= getUp(q[tl-2],q[tl-1],i)*getDown(q[tl-1],j)) tl--;            q[tl++] = j;        }    }    LL ans = 1e12;    for(int i=1;i<=k;i++) ans = min(ans,dp[i][n]);    printf("%lld\n",ans);}int main(){    while(~scanf("%lld%lld",&n,&k)){        init();        Nod o;        for(LL i=0;i<n;i++){            scanf("%lld%lld",&o.w,&o.h);            vec.push_back(o);        }        sort(vec.begin(),vec.end());        n = 0;        for(LL i=0;i<vec.size();i++){            while(n >= 1 && vec[i].h >= h[n]) n--;            n++;            w[n] = vec[i].w;h[n] = vec[i].h;        }        solve();    }    return 0;}


0 0
原创粉丝点击