趣學演算法NYOJ 阿里巴巴與四十大盜
題目描述:
有一天,阿里巴巴趕著一頭毛驢上山砍柴。砍好柴準備下山時,遠處突然出現一股煙塵,瀰漫著直向上空飛揚,朝他這兒捲過來,而且越來越近。靠近以後,他才看清原來是一支馬隊,他們共有四十人,一個個年輕力壯、行動敏捷。一個首領模樣的人揹負沉重的鞍袋,從叢林中一直來到那個大石頭跟前,喃喃地說道:“芝麻,開門吧!”隨著那個頭目的喊聲,大石頭前突然出現一道寬闊的門路,於是強盜們魚貫而入。阿里巴巴待在樹上觀察他們,直到他們走得無影無蹤之後,才從樹上下來。他大聲喊道:“芝麻,開門吧!”他的喊聲剛落,洞門立刻打開了。他小心翼翼地走了進去,一下子驚呆了,洞中堆滿了財物,還有多得無法計數的金銀珠寶,有的散堆在地上,有的盛在皮袋中。突然看見這麼多的金銀財富,阿里巴巴深信這肯定是一個強盜們數代經營、掠奪所積累起來的寶窟。為了讓鄉親們開開眼界,見識一下這些寶物,他想一種寶物只拿一個,如果太重就用錘子鑿開,但毛驢的運載能力是有限的,怎麼才能用驢子運走最大價值的財寶分給窮人呢?阿里巴巴陷入沉思中……
假設山洞中有n種寶物,每種寶物有一定重量w和相應的價值v,毛驢運載能力有限,只能運走m重量的寶物,一種寶物只能拿一樣,寶物可以分割。那麼怎麼才能使毛驢運走寶物的價值最大呢?
輸入描述:
第一行是一個整型數m(m<100)表示共有m組測試資料。
每組測試資料的第一行是兩個整數n,c (1<n,c<10000)表示該測試資料寶物數量及驢子的承載重量。
隨後的n行,每行有兩個正整數wi, vi分別表示第i個寶物的重量和價值(1<wi,vi<100)。
輸出描述:
對於每一組輸入,輸出毛驢運走寶物的最大價值。
每組的輸出佔一行
樣例輸入:
2
6 19
2 8
6 1
7 9
4 3
10 2
3 4
5 60
5 12
20 45
35 70
12 38
6 15
樣例輸出:
24.6
144
這也是最為基礎的貪心演算法題,由於寶物是可以分割的,我們對寶物要根據其價效比,也就是相同重量所能獲得到的利益來進行排序,然後在根據排序所得到的結構體陣列,依次往驢身上新增寶物,如果寶物可以整體放入則直接放入,然後調整當前所獲得的利益以及空餘的可放置寶物的重量,最後肯定有寶物無法直接放入,這個時候的寶物需要分割,只需根據前面計算所得的空餘質量位乘以這個寶物的價效比就是最後所獲得的利益,此時需要跳出迴圈,演算法結束。
#include<iostream>
#include<algorithm>
using namespace std;
const int Size= 10001;
struct Treasure{
double value;
double weight;
double xjb;
};
bool cmp(Treasure A,Treasure B){
return A.xjb>B.xjb;
}
int main(){
int num;
Treasure baowu[Size];
cin>>num;
int num_baowu;
double lv;
while(num--){
cin>>num_baowu>>lv;
for(int i=0;i<num_baowu;i++){
cin>>baowu[i].weight>>baowu[i].value;
baowu[i].xjb=baowu[i].value/baowu[i].weight;
}
sort(baowu,baowu+num_baowu,cmp);
double ans=0;
for(int i=0;i<num_baowu;i++){
if(baowu[i].weight<lv){
lv-=baowu[i].weight;
ans+=baowu[i].value;
}
else{
ans+=lv*baowu[i].xjb;
break;
}
}
cout<<ans<<endl;
}
return 0;
}