01背包问题是最经典的背包问题,没有之一。
关于背包问题,我举过一个例子,有一天,阿里巴巴背着一个背包来到了山洞里,面对大量的金银财宝,他的背包却容量有限,他要如何选择呢?假如说这些财宝可以无限分割,例如是金粉,银粉,铜粉,他只要贪心地先放金,再放银,最后放铜,直到装满,那么如果这些财宝各有体积且无法切割,很显然,贪心无法解决这个问题,那么就只能使用动态规划了。
举个例题
Bone Collector
Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 128982    Accepted Submission(s): 51264
Problem Description
Many years ago , in Teddy’s hometown there was a man who was called “Bone Collector”. This man like to collect varies of bones , such as dog’s , cow’s , also he went to the grave …
The bone collector had a big bag with a volume of V ,and along his trip of collecting there are a lot of bones , obviously , different bone has different value and different volume, now given the each bone’s value along his trip , can you calculate out the maximum of the total value the bone collector can get ?
The bone collector had a big bag with a volume of V ,and along his trip of collecting there are a lot of bones , obviously , different bone has different value and different volume, now given the each bone’s value along his trip , can you calculate out the maximum of the total value the bone collector can get ?
Input
The first line contain a integer T , the number of cases.
Followed by T cases , each case three lines , the first line contain two integer N , V, (N <= 1000 , V <= 1000 )representing the number of bones and the volume of his bag. And the second line contain N integers representing the value of each bone. The third line contain N integers representing the volume of each bone.
Followed by T cases , each case three lines , the first line contain two integer N , V, (N <= 1000 , V <= 1000 )representing the number of bones and the volume of his bag. And the second line contain N integers representing the value of each bone. The third line contain N integers representing the volume of each bone.
Output
One integer per line representing the maximum of the total value (this number will be less than 231).
Sample Input
1
5 10
1 2 3 4 5
5 4 3 2 1
Sample Output
14
本题为01背包裸题,其状态转移方程为dp[i][j]=max(dp[i-1][j],dp[i-1][j-w[i]]+v[i]),dp[i][j]表示遍历到第i个物品,使用了j的容量时得到的最大价值,其值由是否将这个物品放入决定。w[i]表示第i个物品的体积,v[i]表示第i个物品的价值。
然而二维的空间实在太多,容易超出内存限制,我们又观察到第i行只由第i-1行决定,于是我们可以将第一个维度删除,状态转移方程变为dp[j]=max(dp[j],dp[j-w[i]]+v[i])。这个操作被称为滚动数组。可是我们又发现这样操作之后原式的dp[i-1][j-w[i]]+v[i]会被覆盖为dp[i][j-w[i]]+v[i],出现了错误,所以在遍历j的时候我们从右往左遍历,这样就不会被覆盖了。
代码如下
#include<iostream> #include<cstdio> #include<cstring> using namespace std; typedef long long ll; ll dp[1005]; int w[1005]; int v[1005]; int main(){ int t; scanf("%d",&t); while(t--){ int n,vo; scanf("%d%d",&n,&vo); for(int i=1;i<=n;i++)scanf("%d",&v[i]); for(int i=1;i<=n;i++)scanf("%d",&w[i]); memset(dp,0,sizeof(dp)); for(int i=1;i<=n;i++){ for(int j=vo;j>=w[i];j--){ dp[j]=max(dp[j],dp[j-w[i]]+v[i]); } } printf("%lld\n",dp[vo]); } return 0; }
 
                    
                 
 
                
            
         浙公网安备 33010602011771号
浙公网安备 33010602011771号