01揹包問題(動態規劃求解)
這兩天c++的習題開始不考察c++了,開始考察動態規劃問題,唉,沒學過動態規劃演算法來編這題目真是一把辛酸淚,下面給出題目(題目來源:郭瑋老師的mooc)
2:Charm Bracelet
檢視 提交 統計 提問
總時間限制: 1000ms 記憶體限制: 65536kB
描述
Bessie has gone to the mall’s jewelry store and spies a charm bracelet. Of course, she’d like to fill it with the best charms possible from the N(1 ≤ N≤ 3,402) available charms. Each charm iin the supplied list has a weight Wi(1 ≤ Wi≤ 400), a ‘desirability’ factor Di(1 ≤ Di≤ 100), and can be used at most once. Bessie can only support a charm bracelet whose weight is no more than M(1 ≤ M≤ 12,880).
Given that weight limit as a constraint and a list of the charms with their weights and desirability rating, deduce the maximum possible sum of ratings.
輸入
Line 1: Two space-separated integers: N and M
Lines 2…N+1: Line i+1 describes charm i with two space-separated integers: Wi and Di
輸出
Line 1: A single integer that is the greatest sum of charm desirabilities that can be achieved given the weight constraints
樣例輸入
4 6
1 4
2 6
3 12
2 7
樣例輸出
23
看上去這題確實不難,真正的題目就是給定總重量m,求最大的desirability
#include <iostream> #include <cstring> #define MAX 3402 using namespace std; class charm; int combine_decrease(int m , charm* arr, int start, int* result, int count, const int NUM); class charm { public: int w; int d; }; int main (void) { int n; int m; int i; int j ; int max_desir = 0; int temp = 0; charm charm_list[MAX] ; int result[MAX] ; cin>>n>>m; for(i=0;i<n;i++){ cin>>charm_list[i].w>>charm_list[i].d; }//have stored the charm; for(i = 1;i <= n; ++i){ temp = combine_decrease(m,charm_list , n , result , i , i ); if (temp >= max_desir) max_desir = temp; } cout<<max_desir; } //arr涓哄師濮嬫暟緇? //start涓洪亶鍘嗚搗濮嬩綅緗? //result淇濆瓨緇撴灉錛屼負涓€緇存暟緇? //count涓簉esult鏁扮粍鐨勭儲寮曞€礆紝璧瘋緟鍔╀綔鐢? //NUM涓鴻閫夊彇鐨勫厓鞝犱釜鏁? int combine_decrease(int m, charm* arr, int start, int* result, int count, const int NUM) { int i; int sum = 0; int temp = 0; int temp_weight = 0; for (i = start; i >=count; i--) { result[count - 1] = i - 1; if (count > 1) { temp = combine_decrease(m,arr, i - 1, result, count - 1, NUM); if(temp >= sum){ sum = temp; } temp = 0; } else { int j; for (j = NUM - 1; j >=0; j--){ temp_weight +=arr[result[j]].w; temp += arr[result[j]].d; //printf("%d ",arr[result[j]].d);; if(temp_weight > m) break; } //cout<<endl; //cout<<"desire:"<<temp<<"weight:"<<temp_weight<<endl; if(temp>=sum && temp_weight <= m) sum = temp; //cout<<"sum:"<<sum<<endl; temp = 0; temp_weight = 0; } } return sum; }
答案確實是做出來了,應該也是對的,然後提交後出現**“超時”**,唉想想也是,遍歷所有情況,想想都害怕,還用遞迴來實現,機子肯定要爆掉。沒辦法實在想不出,上網查資料。
一查就查到了,這是經典的01揹包問題,也就是經典的動態規劃求解問題:
程式碼來源https://blog.csdn.net/qingboda110/article/details/51050299
#include<stdio.h>
int W[3500];
int D[3500];
int f[13000];
int main(){
int ans,max,n,i,j;
scanf("%d",&n);
scanf("%d",&max);
for(i=0;i<n;i++){
scanf("%d",&W[i]);
scanf("%d",&D[i]);
}
for(i=0;i<n;i++){
for(j=max;j>0;j--){
if(j>=W[i]&&f[j]<f[j-W[i]]+D[i])
f[j]=f[j-W[i]]+D[i];
}
}
ans=0;
for(i=0;i<=max;i++){
if(f[i]>ans)
ans=f[i];
}
printf("%d\n",ans);
return 0;
}