1. 程式人生 > >通過洛谷P2639看01背包

通過洛谷P2639看01背包

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     }
11
for(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背包