http://poj.org/problem?id=3253
挑战上的题,但是我是实在不会。后来看到他的文字解释慢慢理解了。
一开始我的贪心策略很简单,我们直接想着每次都把最长的给去掉即可,这样下一次得到的木板长度是该处操作去掉任何一个长度木板中最短的了。但是的贪心是有反例的。比如4 4 4 4,最小的花费应该是32,而这样贪心算到的是36.
那么我们就要换换思路了。其实我们上面的贪心几乎接近正确了,但是我们不能正着看问题,要逆着看。我们上面贪心,在最后的最后,肯定是取得最短和次短的木板。然后我们把这个木板合并起来,我们继续取最短和次短,不断循环,直到最后只剩下了一个木板,就可以停止了。
例如4 4 4 4的样例,我们取得4 4,那么ans += 8,然后在4 4 8中,继续取4 4,ans+=8,然后8 8中取得8 8,ans += 16,所以ans = 32。
而对于5 8 8,取得5 8,ans += 13, 在8 13中ans+=21,所以ans = 34.
代码如下:
#include<queue>
#include<iostream>
using namespace std;
typedef long long ll;
int n;
int main(){
long long ans = 0, tmp;
priority_queue<ll, vector<ll>, greater<ll> >q;
cin >> n;
for(int i = 0; i < n; i++){
cin >> tmp;
q.push(tmp);
}
while(q.size() > 1){
tmp = 0;
tmp += q.top();
q.pop();
tmp += q.top();
q.pop();
ans += tmp;
q.push(tmp);
}
cout << ans << endl;
return 0;
}