poj-3253

来源:互联网 发布:乘联会新能源销量数据 编辑:程序博客网 时间:2024/06/08 10:40
#include <iostream>
#include <queue>
#include <vector>
#include <cstring>

using namespace std;

priority_queue<long long, vector<long long>, greater<long long> > intQueue;

const int QUEUE_SIZE = 20010;

template <typename T>
struct LessComparator {
    char operator()(const T & p1, const T & p2) {
        return p1 < p2;
    }
};
 

template <typename T, class C>
class my_priroity_queue {
private:
    T mArray[QUEUE_SIZE];
    int mQueueSize;
    C mComparator;

    void adjust_heap_node_up(int NodePos) {
        int parentPos = NodePos;
        int leftChildPos = 2*NodePos + 1;
        int rightChildPos = 2*NodePos + 2;

        // cout<<"p "<<parentPos<<" l "<<leftChildPos<<" r "<<rightChildPos<<" "<<mArray[leftChildPos]<<" "<<mArray[parentPos]<<" "<<mArray[rightChildPos]<<endl;

        if (rightChildPos + 1 <= mQueueSize) {  // 2
            int min = mComparator(mArray[parentPos], mArray[leftChildPos]) ? parentPos : leftChildPos;
            min =  mComparator(mArray[min], mArray[rightChildPos]) ? min : rightChildPos;
            if (min == parentPos) {
                // cout<<"2 == "<<parentPos<<" "<<mArray[leftChildPos]<<" "<<mArray[parentPos]<<" "<<mArray[rightChildPos]<<endl;
                return;
            } else {
                T tmp = mArray[min];
                mArray[min] = mArray[parentPos];
                mArray[parentPos] = tmp;
                if (!parentPos) {
                    return;
                }
                adjust_heap_node_up((parentPos-1)/2);
            }
        } else if (leftChildPos + 1 <= mQueueSize){  // 1
            int min = mComparator(mArray[parentPos], mArray[leftChildPos]) ? parentPos : leftChildPos;
            if (min == parentPos) {
                // cout<<"1 == "<<parentPos<<endl;
                return;
            } else {
                T tmp = mArray[min];
                mArray[min] = mArray[parentPos];
                mArray[parentPos] = tmp;
                if (!parentPos) {
                    return;
                }
                adjust_heap_node_up((parentPos-1)/2);   
            }
        } else {
            // cout<<"3 return "<<NodePos<<endl;
            return;
        }    
    }

    void adjust_heap_node_down(int NodePos) {
        int parentPos = NodePos;
        int leftChildPos = 2*NodePos + 1;
        int rightChildPos = 2*NodePos + 2;

        if (rightChildPos + 1 <= mQueueSize) {  // 2
            int min = mComparator(mArray[parentPos], mArray[leftChildPos]) ? parentPos : leftChildPos;
            min =  mComparator(mArray[min], mArray[rightChildPos]) ? min : rightChildPos;
            if (min == parentPos) {
                return;
            } else {
                T tmp = mArray[min];
                mArray[min] = mArray[parentPos];
                mArray[parentPos] = tmp;
                if (min*2 + 2 + 1 > mQueueSize) {
                    return;
                }
                adjust_heap_node_down(min);
            }
        } else if (leftChildPos + 1 <= mQueueSize){  // 1
            int min = mComparator(mArray[parentPos], mArray[leftChildPos]) ? parentPos : leftChildPos;
            if (min == parentPos) {
                return;
            } else {
                T tmp = mArray[min];
                mArray[min] = mArray[parentPos];
                mArray[parentPos] = tmp;
                if (min*2 + 1 + 1 > mQueueSize) {
                    return;
                }
                adjust_heap_node_down(min);   
            }
        } else {
            // cout<<"3 return "<<NodePos<<endl;
            return;
        }    
    }

    void matain_heap_after_insert() {
        int beginNode = (mQueueSize-2)/2;
        adjust_heap_node_up(beginNode);
    }

    void matain_heap_after_pop() {
        int beginNode = 0;
        adjust_heap_node_down(beginNode);
    }


public:
    my_priroity_queue(C cmp):  mQueueSize(0), mComparator(cmp) {
        memset(mArray, 0, sizeof(mArray));
    }

    T top() {
        return mArray[0];
    }

    void push(T val) {
        mArray[mQueueSize++] = val;
        matain_heap_after_insert();
        // cout<<"size "<<mQueueSize<<endl;
        // for (int i = 0; i < mQueueSize; i++) {
        //     cout<<mArray[i]<<endl;
        // }
    }

    void pop() {
        if (mQueueSize) {
            mArray[0] = mArray[--mQueueSize];
            if (mQueueSize) {
                matain_heap_after_pop();
            }
        }
    }

    int size() {
        return mQueueSize;
    }

};

struct LessComparator<long long> cmp;
my_priroity_queue<long long, struct LessComparator<long long> > my_queue(cmp);

void getMinCost() {
    long long totalCost = 0;
    while(my_queue.size() > 1) {
        long long costThisTime = my_queue.top();
        // cout<<my_queue.top()<<endl;
        my_queue.pop();
        costThisTime += my_queue.top();
        // cout<<my_queue.top()<<endl;
        my_queue.pop();
        my_queue.push(costThisTime);
        totalCost += costThisTime;
    }
    //totalCost += intQueue.top();
    my_queue.pop();
    cout<<totalCost<<endl;
}


int TEST() {
    cout<<"TEST"<<endl;
    my_queue.push(537);
    my_queue.push(4189);
    my_queue.push(652);
    my_queue.push(3127);
    // my_queue.pop();
    // cout<<"RES"<<endl;
    // while(my_queue.size()) {
    //     cout<<my_queue.top()<<endl;
    //     my_queue.pop();
    // }
    my_queue.push(4673);
    my_queue.push(1364);
    my_queue.push(40);
    // my_queue.pop();
    // cout<<"RES"<<endl;
    // while(my_queue.size()) {
    //     cout<<my_queue.top()<<endl;
    //     my_queue.pop();
    // }
    my_queue.push(854);
    my_queue.push(2326);
    my_queue.push(1016);
    my_queue.push(1307);
    my_queue.push(3372);
    my_queue.push(4663);
    my_queue.push(2164);
    my_queue.push(2833);
    my_queue.push(3037);
    my_queue.push(4758);
    my_queue.push(4757);
    my_queue.push(4633);
    my_queue.push(2942);
    cout<<"RES"<<endl;
    my_queue.pop();
    my_queue.pop();
    my_queue.push(577);
    while(my_queue.size()) {
        cout<<my_queue.top()<<endl;
        my_queue.pop();
    }
}

int main() {
    // TEST();
    while(1) {
        int num = 0;
        cin>>num;
        if (cin.eof()) {
            return 0;
        }
        // intQueue.clear();
        for (int i = 0; i < num; i++) {
            long long tmp;
            cin>>tmp;
            my_queue.push(tmp);
        }
        getMinCost();
        // while(intQueue.size()) {
        //     cout<<intQueue.top()<<endl;
        //     intQueue.pop();
        // }
    }

}


C++ 94ms(STL queue)

G++ 157MS(自己写的优先级queue)

用了哈夫曼树的原理,以及STL的 priority_queue.

这道题让我重新认识了哈夫曼树,以前对哈夫曼树的认识被局限在那个求编码的例子中。

遇到这道题根本没想到能用哈夫曼,一开始想用动态规划来着,后来发现虽然DP理论上可以用,但是结合这道题是基本不行的,因为数位太多了(20000)

后来看到有说可以用哈夫曼,但是不理解为什么能够向哈夫曼树转化,后来仔细读了算导的哈夫曼树:

哈夫曼树能得到这样的最小值,对于一系列的值Array[i]:

D(i)*Array(i)的全部和最小。 其中 D(i)是该值(叶子节点)在哈夫曼树中的深度,Array[i]是数组的第i个值。

那么对于本题来说,按照锯木头的顺序来构造一颗二叉树,那么总和花费也可以表示为:

D(i)*L(i)的总和, D(i) 是第i个plank在树中的深度,而L(i)则是plank i的长度,为什么总花费能够用这样表示,

是因为,对于某个plank来说,从开始切割到最后终于将plank  i切割出去,因为plank i带来的cost一共就是D(i)*L(i), 

举个简单例子, 5个plank, L: 1 2 3 4 5

这样切割的顺序:

                                   12345

                            12          345

                        1       2       3      45

                                                4       5

可以看到,切割4/5的总代价就是其本身长度乘以其深度(这是因为除非plank被切割出去,否则必然会参与下一次分割,那么其长度就会附加到下一次的切割花费中)。

也可以称此题为求该树全部父节点和最小的问题(因为每个父节点必是一次切割,代价则是两个子节点的代价和)

这样,就能转化为哈夫曼树的问题了。

要记住这个经典的哈夫曼树运用模式。

还有需要注意的是,最后的cost要用long long

自己写优先级queue的时候,在求父子节点index的表示时,因为数组index是从0开始的,

因此对于父节点index = p,子节点inex: left = 2*p + 1 right = 2*right + 2

而对于子节点index = i, 其父节点应该为(i-2)/2。

队列对于解某些算法题确实是好东西,BFS也经常用到.         


0 0
原创粉丝点击