HDU 1257 最少拦截系统 dp + 贪心

http://acm.hdu.edu.cn/showproblem.php?pid=1257

一开始的时候还用了单调栈维护,toNext[i] 表示第i个往右边,第一个比它小的数。

我还以为一路这样弄下去就搞定了。

但是有数据卡我了。

6 5 6 5 4 3 2 1 5 4 3 2 1

这样其实只需要两个。但是我的做法会输出3个。。

正解是一个简单的dp

dp[i]表示第i个导弹拦截的最小高度。

然后用一个ans记录一共用了多少枚导弹

每有一个新的值,就优先找一枚合法的导弹放进去就行了。

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#define IOS ios::sync_with_stdio(false)
using namespace std;
#define inf (0x3f3f3f3f)
typedef long long int LL;

#include <iostream>
#include <sstream>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <string>
const int maxn = 30000 + 20;
int dp[maxn];
int n;
void work() {
//    memset(dp, 0x3f, sizeof dp);
    int ans = 0;
    for (int i = 1; i <= n; ++i) {
        int a;
        scanf("%d", &a);
        int j;
        for (j = 1; j <= ans; ++j) {
            if (dp[j] >= a) {
                dp[j] = a;
                break;
            }
        }
        if (j == ans + 1) dp[++ans] = a;
    }
    cout << ans << endl;
}

int main() {
#ifdef local
    freopen("data.txt","r",stdin);
#endif
    while (scanf("%d", &n) != EOF) work();
    return 0;
}
View Code

这题还有另外一个做法。

采用逆向思维,现在它是要分成若干个最长不升子序列。

那么相反的就是最长上升子序列。输出长度即可。

为什么呢?

因为最长上升子序列,都是选取一些尽可能小的点组合成的,而这些点,刚好就是没得下降的点啦。

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#define IOS ios::sync_with_stdio(false)
using namespace std;
#define inf (0x3f3f3f3f)
typedef long long int LL;

#include <iostream>
#include <sstream>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <string>
const int maxn = 30000 + 20;
int dp[maxn];
int a[maxn];
int n;
void work() {
    int lendp = 0;
    for (int i = 1; i <= n; ++i) cin >> a[i];
    dp[++lendp] = a[1];
    for (int i = 2; i <= n; ++i) {
        if (a[i] > dp[lendp]) {
            dp[++lendp] = a[i];
        } else {
            int pos = lower_bound(dp + 1, dp + 1 + lendp, a[i]) - dp;
            dp[pos] = a[i];
        }
    }
    cout << lendp << endl;
}

int main() {
#ifdef local
    freopen("data.txt","r",stdin);
#endif
    while (cin >> n) work();
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/liuweimingcprogram/p/6005211.html