貪心演算法解決0-1揹包問題
阿新 • • 發佈:2019-01-03
揹包問題描述如下: 已知
揹包容量M=120
物品種類數n=10
各種物品的總效益pi(i=1,2,………10) : 50,60,70,80,90,80,70,60,50,40
各種物品的總重量wi(i=1,2………10) : 17,30,25,41,80,70,64,56,47,38
求: 各種物品所取重量佔其總重量的比例xi(i=1,2,…..10),滿足0<=xi<=1,
按三種不同的量度標準分別計算所得最大總效益
1. 按效益值由大到小取物品
2. 按重量值由小到大取物品
3. 按比值pi/wi的值由大到小取物品
貪心演算法思想
資料結構採用結構體來表示一個物品。按照各種量度標準排序物品。對於每一種排序結果,在揹包容量內,選擇量度最大的物品,繼續選擇次量度最大的物品,直到選到當前量度最大物品的重量大於揹包剩餘容量時(容不下),放入物品的一部分,這部分和揹包剩餘容量相等。打印出各物品是否被選擇,或者被選擇的比例。
程式程式碼
#include <iostream> #include <algorithm> #include <iomanip> #include <cstdio> using namespace std; struct form { int i; //為方便後序列印結果,設定物品序號 int pi; int wi; float xi; int flag; //標誌一整個物品被選取 float floflag; //標誌物品被選取的那一部分 }; int bag, thingNum; int cmpPi( form a, form b ) //按效益值從大到小排序 { return a.pi > b.pi; } int cmpWi( form a, form b ) //按重量從小到大排序 { return a.wi < b.wi; } int cmpXi( form a, form b ) //按比例從大到小排序 { return a.xi > b.xi; } void print( form *things, int thingNum ) { printf( "物品序號 " ); for( int i = 0; i < thingNum; i++ ) printf( "%-6d", i ); printf( "總效益\n " ); float ans = 0; //總效益,邊列印邊計算 for( int i = 0; i < thingNum; i++ ) { for( int j = 0; j < thingNum; j++ ) { if( things[j].i == i ) { if( things[j].floflag != 0 ) { printf( "%-6.3f", things[j].floflag ); ans += things[j].floflag * things[j].pi ; things[j].floflag = 0; //置零初始化 } else { printf( "%-6d", things[j].flag ); if( things[j].flag == 1 ) ans += things[j].pi ; things[j].flag = 0; //置零初始化 } continue; } } } printf( "%-6.2f\n", ans ); for( int i = 0; i < 100; i++ ) printf( "-" ); printf( "\n" ); } void select( form *things ) //選取物品 { int res = bag; for( int i = 0; i < thingNum; i++ ) { if( things[i].wi < res ) { things[i].flag = 1; things[i].floflag = 0; res -= things[i].wi; } else { things[i].flag = 0; things[i].floflag = ( 1.0 * res ) / things[i].wi; break; } } } void value( form *things ) { sort( things, things + thingNum, cmpPi ); select( things ); printf( "按效益值\n" ) ; print( things, thingNum ); } void weight( form *things ) { sort( things, things + thingNum, cmpWi ); printf( "\n" ); select( things ); printf( "按重量\n" ); print( things, thingNum ); } void speVal( form *things ) { sort( things, things + thingNum, cmpXi ); cout << endl; select( things ); printf( "按比值\n" ) ; print( things, thingNum ); } int main( ) { printf( "請輸入揹包容量,物品數目:\n" ); scanf( "%d%d", &bag, &thingNum ); printf( "輸入每個物品的效益和重量:\n" ); form things[thingNum]; for( int i = 0; i < thingNum; i++ ) { scanf( "%d%d", &things[i].pi, &things[i].wi ); things[i].i = i; things[i].xi = 1.0 * things[i].pi / things[i].wi; things[i].flag = things[i].floflag = 0; //初始化 } value( things ); //按效益值 weight( things ); //按重量值 speVal( things ); // 按比值 return 0; }
題目資料樣例
120 10
50 17
60 30
70 25
80 41
90 80
80 70
70 64
60 56
50 47
40 38
輸出樣例