777E Hanoi Factory

来源:互联网 发布:amtemu mac用不了 编辑:程序博客网 时间:2024/05/16 04:43

Of course you have heard the famous task about Hanoi Towers, but did you know that there is a special factory producing the rings for this wonderful game? Once upon a time, the ruler of the ancient Egypt ordered the workers of Hanoi Factory to create as high tower as possible. They were not ready to serve such a strange order so they had to create this new tower using already produced rings.

There are n rings in factory's stock. Thei-th ring has inner radiusai, outer radiusbi and heighthi. The goal is to select some subset of rings and arrange them such that the following conditions are satisfied:

  • Outer radiuses form a non-increasing sequence, i.e. one can put the j-th ring on the i-th ring only ifbj ≤ bi.
  • Rings should not fall one into the the other. That means one can place ring j on the ring i only if bj > ai.
  • The total height of all rings used should be maximum possible.
Input

The first line of the input contains a single integer n (1 ≤ n ≤ 100 000) — the number of rings in factory's stock.

The i-th of the next n lines contains three integers ai,bi andhi (1 ≤ ai, bi, hi ≤ 109,bi > ai) — inner radius, outer radius and the height of thei-th ring respectively.

Output

Print one integer — the maximum height of the tower that can be obtained.

题目的意思就是用环来搭汉诺塔,每个环有内径a,外径b和高h,搭的时候上面环外径的要比下面的小,但是不能掉下去,也就是上面的环外径要比下面的环内径大。输入一些环的内径,外径,高度,求用这些环能搭的汉诺塔的最大高度。

主要用排序+动态规划,按tutorial的思路写了一遍。首先做一个处理,所有的外径一样的环可以看作把这些环叠在一起变成一个环,这是一定可以做到的,这些环的内径一定小于它们的外径,所以高度是这些环高度的总和,内径取最小的,就是相当于把内径最小的环放在最上面。将这些环按外径从大到小,保证在后面的环一定是后放上去的。然后就是动态规划,用dp[i]表示最上面的环是第i个环所能达到的最大高度,很直接的想法就是看第i个环能不能放到前面的i-1个环上,如果能放到某个环j上,新的高度就是dp[j]+第i个环的高度。取最大的为dp[i](前面i-1个上面都不能放,dp[i]就是环i的高度)。最后的答案就是所有dp[i]中最大的。(超时,只过了十几个样例)

可以再优化,注意到,如果第k个环可以放到第i个环和第j个环上(i < j < k),那么第j个环一定可以放到第i个环上(ring[i].a < ring[k].b, ring[k].b < ring[j].b, 于是ring[i].a < ring[j].b),所以如果环k可以放到第i和第j个环上(i<j),那么一定有dp[j] >= dp[i],所以求dp[k]的时候动第第k-1个环往前找,找到的第一个满足ring[j].a < ring[k].b的j就是最大的。(还是超时,过了40多个样例)

继续优化,越往上放的环越小,所以那些不能放在第i个环下面的一定也不能放在第i个环之后的所有环下面。tutorial里面给了一种用栈的做法,可以被放在下面的环留在栈里面,不能被放在下面的环出栈。还有一种是维持一个按内径大小排好序的序列,想法类似,内径大的那些不要管。

#include<iostream>#include<vector>#include<algorithm>#include<stack>using namespace std;struct ring {int a, b, h;bool operator<(const ring& r) {return this->a < r.a;}};bool cmp(ring r1, ring r2) {return r1.b > r2.b;}int main() {int n; cin >> n;vector<ring> rings;for (int i = 0; i < n; i++) {ring r; cin >> r.a >> r.b >> r.h;rings.push_back(r);}ring what; what.b = -1;rings.push_back(what);sort(rings.begin(), rings.end(), cmp);vector<ring> temp;ring r = rings[0];for (int i = 1; i < n + 1; i++) {if (rings[i].b == rings[i - 1].b) {r.a = r.a < rings[i].a ? r.a : rings[i].a;r.h += rings[i].h;}else {temp.push_back(r);r = rings[i];}}int n2 = temp.size();vector<long long> dp(n2, 0);dp[0] = temp[0].h;stack<int> satisfy;satisfy.push(0);for (int i = 1; i < n2; i++) {/*long long m = temp[i].h;int j;for (j = i - 1; j >= 0; j--) {if (temp[j].a < temp[i].b) {if (dp[j] + temp[i].h > m) {m = dp[j] + temp[i].h;}break;}}dp[i] = m;*/while (!satisfy.empty()) {if (temp[satisfy.top()].a >= temp[i].b) satisfy.pop();else break;}if (!satisfy.empty()) dp[i] = dp[satisfy.top()];dp[i] +=temp[i].h;satisfy.push(i);}long long m = 0;for (int i = 0; i < n2; i++) {if (dp[i] > m) m = dp[i];}cout << m << endl;}


0 0
原创粉丝点击