ACM知識點 之 貪心(4)部分揹包問題
阿新 • • 發佈:2018-12-23
部分揹包問題雖說是歸於揹包問題的一種,而且揹包問題大多數是通過動態規劃的出的結果,但是貪心演算法解部分揹包,不管是思想還是操作上來說,都是非常簡單的。
首先,我們來看一下什麼叫做部分揹包。
有N個商品,每個商品的重量為WI,價格為:PI,現有一個揹包,最多能裝M的重量.
其中(0<=I< N,0< wi<.M).
問:怎樣裝能使包中裝入的商品價值最高(對於每個商品可以只裝該商品的一部分)
那我們就來分析一下條件::
1. 商品重量不是無限的。
那就說明我們不能只拿一種東西,大多數情況都要進行多個物品的選取。
2. 商品可以被拆分成部分。
那就說明我們需要考慮的不僅是“這個物品能不能裝”?,還要考慮“裝多少”? 在這兩種情況下,我們需要考慮的是不能是物品的價值,而是價效比。
3. 商品的屬性有兩個:重量和價格;
根據這兩個屬性,我們可以計算出商品的價效比,也就是單價。
4. 要求裝入揹包中的物品價格最高
那就是說,我們需要按照價效比從高到低的順序進行,依次裝入我們需要得物品,直到揹包裝滿。
由於是按照價效比從高到低的順序進行的選取,那麼同樣重量的揹包,這種方法獲得的價值是所有方法中最大的。
所以我們可以大概寫出偽程式碼表示整個求解過程:
sort 先把各個物品按照單價從高到低排序 for(迴圈每一個物品) { if(物品的重量小於揹包剩餘的重量) { 揹包剩餘的重量 -= 物品總重量; 總價值 += 物品總價值; }else { 總價值 += 物品單價*揹包剩餘重量; 退出迴圈; } }
揹包問題
時間限制:3000 ms | 記憶體限制:65535 KB
難度:3
描述
現在有很多物品(它們是可以分割的),我們知道它們每個物品的單位重量的價值v和重量w(1<=v,w<=10);如果給你一個揹包它能容納的重量為m(10<=m<=20),你所要做的就是把物品裝到揹包裡,使揹包裡的物品的價值總和最大。
輸入
第一行輸入一個正整數n(1<=n<=5),表示有n組測試資料;
隨後有n測試資料,每組測試資料的第一行有兩個正整數s,m(1<=s<=10);s表示有s個物品。接下來的s行每行有兩個正整數v,w。
輸出
輸出每組測試資料中揹包內的物品的價值和,每次輸出佔一行。
樣例輸入
1
3 15
5 10
2 8
3 9
樣例輸出
65
和之前的分析過程一樣,而且這道題直接給的單價,所以更方便,直接上程式碼:
/*
************************************
Title: NYOJ 106-揹包問題
************************************
Date:2015/07/23
************************************
author:劉旭
************************************
Memory:232KB
Time:0ms
************************************
*/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define MAX 105
struct Node
{
int w;
int v;
};
Node map[MAX];
bool cmp(Node a,Node b)
{
if(a.v != b.v)
{
return a.v > b.v;
}
return a.w > b.w;
}
int main()
{
int T = 0;
scanf("%d", &T);
while(T--)
{
memset(map, -1, sizeof(map));
int num = 0;
int weight = 0;
scanf("%d%d", &num, &weight);
for(int i = 0; i < num; i++)
{
scanf("%d%d", &map[i].v, &map[i].w);
}
sort(map, map+num, cmp);
int ans = 0;
for(int i = 0; i < num; i++){
if(weight >= map[i].w){
weight -= map[i].w;
ans += map[i].v * map[i].w;
}else{
ans += map[i].v * weight;
break;
}
}
printf("%d\n", ans);
}
return 0;
}