Greedy --- HNU 13320 Please, go first

Problem's Link: http://acm.hnu.cn/online/?action=problem&type=show&id=13320


Mean:

n个人一起去滑雪,要坐电梯到山顶,电梯每5分钟可以送一个人上去。这n个人中有的是组好团一起滑雪的,所以要等到齐了才能开始滑。

但是他们到达电梯下的时间都不是统一的,对于单独一个人来说,他在山下等和在山上等的时间都是一样的。

但是对于n个人的集体来说,如果让他后面的人先上去,这样可能会更节省时间。

求通过调整上电梯的顺序后最多可以节省多少时间。(PS:被这鬼题意坑死 ==||)

analyse:

典型的贪心题。

首先我们来分析未调整之前的状态:

对于一个人,不管你来得多早,你还是得等到和你一个团的最后来的那个人才能开始滑雪。

这样时间浪费在哪里了呢?如果是这种情况:AABBBBBBBBBBBBBBABBB,如果我们变成AAABBBBBBBBBBBBBBBBB,

虽然B团队的时间没变,但是对于A团队来说却节省了很多时间。要贪心的地方就在这。

如何贪呢?

首先需要明确的是:我们不能把同一个团中最后到的那个人提前(人都还没到怎么提),而只能把中间掺杂的其他团的人提前,

而最优情况肯定是:让同一个团的尽量聚合在一起,这样等待的时间才是最少的。

综合这两个条件,我们首先求出未调整队形之前的每种元素的最左边的的位置。

然后按照这个数组来个字符串排序(1.同一个团队的人聚合在一起;2.不同团队之间按照最后的人位置来排序)。

最后对于每个元素,我们求这个元素调整前和调整后的位置之差,累加,最后*5即得答案。

Time complexity: O(N)

Source code:

/*

* this code is made by crazyacking

* Verdict: Accepted

* Submission Date: 2015-07-26-22.01

* Time: 0MS

* Memory: 137KB

*/

#include <queue>

#include <cstdio>

#include <set>

#include <string>

#include <stack>

#include <cmath>

#include <climits>

#include <map>

#include <cstdlib>

#include <iostream>

#include <vector>

#include <algorithm>

#include <cstring>

#define LL long long

#define ULL unsigned long long

using namespace std;

const int MAXN = 25010;

char s[MAXN];

int orp[125], nrp[125], t, n;

bool cmp( char a, char b ) {return orp[a] < orp[b];}

int main()

{

ios_base::sync_with_stdio( false );

cin.tie( 0 );

cin >> t;

while( t-- )

{

cin >> n >> s;

for( int i = 0; i < n; ++i ) orp[s[i]] = i;

sort( s, s + n, cmp );

for( int i = 0; i < n; ++i ) nrp[s[i]] = i;

long long ans = 0;

for( int i = 0; i < n; ++i ) ans += abs( orp[s[i]] - nrp[s[i]] );

cout << ans * 5 << endl;

}

return 0;

}

/*

*/