通過洛谷P2639看01背包
阿新 • • 發佈:2018-04-12
AC 體積 color 完全 文件 嚴格 代碼 farmer 區間
題目描述 Bessie像她的諸多姊妹一樣,因為從Farmer John的草地吃了太多美味的草而長出了太多的贅肉。所以FJ將她置於一個及其嚴格的節食計劃之中。她每天不能吃多過H (5 <= H <= 45,000)公斤的幹草。 Bessie只能吃一整捆幹草;當她開始吃一捆幹草的之後就再也停不下來了。她有一個完整的N (1 <= N <= 500)捆可以給她當作晚餐的幹草的清單。她自然想要盡量吃到更多的幹草。很自然地,每捆幹草只能被吃一次(即使在列表中相同的重量可能出現2次,但是這表示的是兩捆幹草,其中每捆幹草最多只能被吃掉一次)。 給定一個列表表示每捆幹草的重量S_i (1 <= S_i <= H), 求Bessie不超過節食的限制的前提下可以吃掉多少幹草(註意一旦她開始吃一捆幹草就會把那一捆幹草全部吃完)。 輸入輸出格式 輸入格式:* 第一行: 兩個由空格隔開的整數: H 和 N * 第2到第N+1行: 第i+1行是一個單獨的整數,表示第i捆幹草的重量S_i。 輸出格式: * 第一行: 一個單獨的整數表示Bessie在限制範圍內最多可以吃多少公斤的幹草。 輸入輸出樣例 輸入樣例#1: 復制 56 4 15 19 20 21 輸出樣例#1: 復制 56 說明 輸入說明: 有四捆草,重量分別是15, 19, 20和21。Bessie在56公斤的限制範圍內想要吃多少就可以吃多少。 輸出說明: Bessie可以吃3捆幹草(重量分別為15, 20, 21)。恰好達到她的56公斤的限制。
看完題面,應當瞬間判斷01背包(搜索超時了)想到記憶化~dp
這個題相對01少了費用,變成了體積,於是就變成了區間最優體積(體積即費用的地位)
下面是代碼
1 #include<iostream> //頭文件 2 using namespace std; 3 int n,m,a[10001],b[10001],f[100001]={0}; //要註意數據範圍 4 int main() 5 { 6 cin>>n>>m; 7 for(int i=1;i<=m;i++) 8 { 9 cin>>a[i]; //輸入每一捆幹草的數量 10 } 11for(int i=1;i<=m;i++) 12 { 13 for(int j=n;j>=a[i];j--) 14 { 15 if(f[j]<=f[j-a[i]]+a[i])f[j]=f[j-a[i]]+a[i]; //因為數據過大,所以要記得優化成一維的 16 } 17 } 18 cout<<f[n]<<endl; //輸出結果 19 return 0; 20 }
現在問題集中在11-17行
即滾動數組優化和j的倒敘枚舉
用一個表格模擬下
搜索代碼的話
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cstring> 5 #include<vector> 6 #include<queue> 7 #include<cstdlib> 8 #include<fstream> 9 #define maxn 868800 10 using std::cin;using std::cout;using std::endl;using std::max;using std::min; 11 int m,n,k,l,a,b,c,v[maxn],f[maxn]; 12 void dfs(int i,int j) 13 { 14 if(j>m) 15 return ; 16 f[j]=1; 17 if(i==n+1) 18 return ; 19 dfs(i+1,j+v[i]); 20 dfs(i+1,j); 21 } 22 int main() 23 { 24 cin>>m>>n; 25 for(int i=1;i<=n;i++) 26 cin>>v[i]; 27 dfs(1,0); 28 for(int i=m;i>=1;i--) 29 if(f[i]==1) 30 { 31 cout<<i<<endl; 32 return 0; 33 } 34 return 0; 35 }
0 | ||||
從第一個開始選,從00開始推有
f(i,j)=max(f(i-1,j-a[i]),f(i-1,j));
f(i%2,j)=max(f(1^i%2,j-a[i]),f(1^i%2,j));
這個沒什麽問題吧
i是從1開始的,所以一開始給出的應該是f(1,m)=0;
所以j是從m開始推出來的
也就是說i,j是確定的狀態;
所以向下推;
不會導致錯誤;
我們再看看完全背包
下篇吧
通過洛谷P2639看01背包