HDU-1506 Largest Rectangle in a Histogram 动态规划

时间:2021-08-26 18:44:40

先粘上TLE的代码,先对高度离散化,然后DP高度求解。复杂度过高。

代码如下:

HDU-1506 Largest Rectangle in a Histogram 动态规划HDU-1506 Largest Rectangle in a Histogram 动态规划View Code
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <map>
#include <iostream>
#include <algorithm>
#define MAXN 100005
using namespace std; 
int N, cnt;

int seq[MAXN], cseq[MAXN];
long long dp[MAXN]; 
map<int,int>mp, rmp; 

void getint( int &c )
{
    char chr;
    while( chr= getchar(), chr< '0'|| chr> '9' ) ;
    c= chr- '0';
    while( chr= getchar(), chr>= '0'&& chr<= '9' )
    {
        c=c* 10+ chr- '0';
    }
} 

inline long long DP()
{
    long long Max = 0;
    for (int i = 0; i < N; ++i) {
        for (int j = 1; j <= mp[seq[i]]; ++j) {
            dp[j] += rmp[j];
            Max = max(Max, dp[j]);
        }
        for (int j = mp[seq[i]]+1; j <= cnt; ++j) {
            dp[j] = 0;
        }
    }
    return Max;
}

int main()
{
    int Max;
    while (scanf("%d", &N), N) {
        cnt = 0;
        memset(dp, 0, sizeof (dp));
        mp.clear(), rmp.clear();
        for (int i = 0; i < N; ++i) {
            getint(seq[i]);
            cseq[i] = seq[i];    
        }
        sort(cseq, cseq+N);
        for (int i = 0; i < N; ++i) {
            if (mp.count(cseq[i]) == 0) {
                mp[cseq[i]] = ++cnt;
                rmp[cnt] = cseq[i];
            }
        }
        printf("%I64d\n", DP());
    }
    return 0;
}

 

后来依据更犀利的解法来构造状态,l[i], r[i],通过维护这两个数组来达到目的。其代表的含义即是当前高度所能够延伸的最左边和最右边。

代码如下:

#include <cstdlib>
#include <cstdio>
#include <cstring> 
#include <iostream> 
#define MAXN 100005
using namespace std;

int N, seq[MAXN], l[MAXN], r[MAXN];

inline long long max(long long x, long long y)
{
    return x > y ? x : y;
}

long long DP()
{
    long long Max = 0;
    for (int i = 2; i <= N; ++i) {
        while (seq[l[i]-1] >= seq[i]) {
            l[i] = l[l[i]-1];
            if (l[i] <= 0) break; // 前面没有加这句话,TLE
        }
    }
    for (int i = N-1; i >= 1; --i) {
        while (seq[r[i]+1] >= seq[i]) {
            r[i] = r[r[i]+1];
            if (r[i] >= N) break;
        }
    }
    for (int i = 1; i <= N; ++i) {
        Max = max(Max, (long long)(1)*seq[i]*(r[i]-l[i]+1));
    }
    return Max;
}

int main()
{
    while (scanf("%d", &N), N) {
        for (int i = 1; i <= N; ++i) {
            scanf("%d", &seq[i]); 
            l[i] = r[i] = i;
        }
        printf("%I64d\n", DP());
    }
    return 0;
}