HDU 4415
題意:
壯哉我Assassin!
E叔有一柄耐久度為m的袖劍,以及n個目標士兵要去解決。
每解決掉一個士兵,消耗袖劍Ai的耐久度,且獲得該士兵的武器,可以使用該武器解決Bi名其他士兵。
E叔要盡可能地消耗更少耐久度解決更多的敵人,求最小消耗與最大殺敵數。
思路:
我們把士兵分為兩個集合:e1與e2,e1的士兵 Bi = 0 , e2 的 Bi > 0.
我們發現,如果能解決e2的任意一個,e2即可全滅,那麼我們對e2根據消耗進行升序排序,消滅e2集合的消耗即為排序後的第一個士兵的Ai;
其次,要盡可能多地解決e1的士兵,則同樣對e1根據消耗進行升序排序,殺到耐久度小於下一士兵Ai為止;
乍一看,最優解就是先全滅e2再用剩下的耐久度消滅e1較小Ai的敵人,用e2剩下的Bi消耗e1較大Ai的敵人;
如果不能全滅e2,則用所有耐久度去解決e1的敵人。
這樣做的確很優了,但還不是最優,考慮這組樣例:
1
4 5
2 1
3 1
5 0
100 0
按照剛才的貪心策略,先解決Bi > 0 的前兩個士兵(用袖劍殺死士兵1,用士兵1的武器殺死士兵2),消耗2耐久度,然後用士兵2的武器解決Ai最大的士兵4,士兵3由於耐久度不夠則無法解決,答案是3 2。
但是我們可以先用袖劍殺死士兵1與士兵2,用這兩個士兵的武器去解決士兵3,4,明顯最優解為4 5。
於是我們對之前貪心策略做出改進:
設用袖劍殺死一個 Bi = 0 的士兵1消耗為a,設用士兵武器殺死一個在 Bi > 0 的集合裡的士兵2,士兵2的最小消耗為b;
如果a < b,則用袖劍解決士兵1,用士兵武器解決士兵2;
否則,則用袖劍解決士兵2,保留士兵武器解決更大消耗的士兵(可能是士兵1);
換而言之,就是E叔面對一個 Bi > 0 的士兵,他說:本來准備用士兵武器殺死你,現在我又不想了,我要用袖劍殺死你,因為你的消耗並不大,我要換回用以殺死你的士兵武器,去殺死消耗更大的敵人。
可能敘述還是有點不清。。這個貪心策略看起來極其像dp,然而它真心不是dp。。以後思路更清晰的時候再改改吧~
代碼:
/*
* @author FreeWifi_novicer
* language : C++/C
*/
#include
#include
#include
#include
#include
#include
#include
#include