codeforces884D(大概是构造,优先队列)

题意:给你n个盒子,最开始有一堆球,把对应数量的球放到盒子里。(简化版)计算分完所有球的penalty。操作方式是,先将一个非空盒子里的球全部倒出,然后将这堆球以你想要的方式放在2~3个盒子里。Penalty是你倒出球的数量。
WA代码:

#include
using namespace std;
vector<int> a;
int main(){
    int n;
    long long ans=0;
    cin>>n;
    for(int i=1;i<=n;i++){
        int num;
        cin>>num;
        a.push_back(num);
    }
    sort(a.begin(),a.end());
    int power=1;
    if(a.size()==1){
        int c=a.back();
        cout<return 0;
    }
    while(a.size()>=4){
        int c;
        c=a.back();
        a.pop_back();
        ans+=c*power;
        c=a.back();
        a.pop_back();
        ans+=c*power;
        power++;
    }
    if(a.size()==3){
        for(int i=1;i<=3;i++){
            int c=a.back();
            a.pop_back();
            ans+=c*power;
        }
    }
    else{
        for(int i=1;i<=2;i++){
            int c=a.back();
            a.pop_back();
            ans+=c*power;
         }
    }
    cout<return 0;
}

分析:WA的思路就是正着分,从大到小一路分开。
但是这样会卡在一组样例上:

6
1 4 4 4 4 4

按照WA代码的思路,分出的顺序是4 4 4 4 4 1,ans=39,但是如果我们按照 4 9 8->4 1 4 4 8-> 4 1 4 4 4 4 的顺序分出的话,ans=38.
问题在于有没有正确理解题中的一句话:

The penalty of the turn is the number of balls Ivan takes from the box during the first step of the turn.

如果正确理解了这句话的话,显然要正着想这道题目是有难度的,要考虑多种情况,并不是简单的从大到小分开就可以解决的。

AC的思路是逆着题意,从分开的阶段一段一段地合成。那么一个优先队列轻松完成

AC代码:

#include
using namespace std;
priority_queue<long long,vector<long long>,greater<long long> > a;
int main(){
    int n;
    long long ans=0;
    cin>>n;
    for(int i=1;i<=n;i++){
        long long num;
        cin>>num;
        a.push(num);
    }
    if(!(n&1)){
        a.push(0);
    }
    while((int)a.size()>1){
        long long x,y,z;
        x=a.top();
        a.pop();
        y=a.top();
        a.pop();
        z=a.top();
        a.pop();
        ans+=(x+y+z);
        a.push(x+y+z);
    }
    cout<return 0;
}

你可能感兴趣的:(codeforces,Cynthia=w=,构造,优先队列)