【Algothrim】 动态规划实例 (Bone Collector)
2016-08-09 15:32
267 查看
[Description]
Many years ago , in Teddy’s hometownthere was a man who was called “Bone Collector”. This man like to collectvaries 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 ofcollecting
there are a lot of bones , obviously , different bone has differentvalue 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.
(1<=T<=200)
Followed by T cases , each case three lines , the first line contain two integerN ,W, (1<=N<=1000 , 1<=W<=1000 )representing
the number of bonesand the volume of his bag.
And the second line contain N integers representing the
value of each bone (1<=Vi<=100). The third line contain N integersrepresenting the volume of each bone (1<=Wi<=100).
[Output]
Print “#t ans” contains one integer perline representing
the maximum of the total value (this number will be less than231).
[Time Limit]
1 sec for C/C++, 2 sec for Java
[Sample Input]
1
5 10
1 2 3 4 5
5 4 3 2 1
[Sample Output]
#1 14
Analysis:
0/1 背包问题,逆序遍历
Answer:
#include <stdio.h>
#include <string.h>
#define MAXN 1002
#define SIZE 5005
#define rint register int
#define is_digit(c) ((c)>='0' && (c)<='9')
#define MAX(x,y) ((x)>(y)?(x):(y))
int Ans,N,W,f[MAXN];
int w[MAXN],v[MAXN];
char buf[SIZE];
void input(int x[])
{
rint i,j,k,c;
fgets(buf,sizeof(buf),stdin);
for (i=j=0;c=buf[i];i++) {
if (!is_digit(c)) continue;
for (k=0;is_digit(c=buf[i]);i++)
k=k*10+c-'0';
x[++j]=k;
}
}
int main(void)
{
rint i,j,t;int T;
setbuf(stdout,NULL);scanf("%d",&T);
for (t=1;t<=T;t++) {
scanf("%d %d",&N,&W);
fgets(buf,sizeof(buf),stdin);
input(v);input(w);
for (j=W;j>=0;j--) f[j]=0;
for (i=1;i<=N;i++)
for (j=W;j>=w[i];j--)
f[j]=MAX(f[j],f[j-w[i]]+v[i]);
printf("#%d %d\n",t,Ans=f[W]);
}
return 0;
}
看了一点背包理论,来做这个题,不知道为啥1维2维,提交了2维的代码后一直不能通过测试用例,才发现用2维和用1维的思路是不一样的。
二维还是用的顺序遍历,一维用的是逆序。
如何理解二维降一维呢?对于外层循环中的每一个i值,其实都是不需要记录的,在第i次循环时,所有的dp[0…v]都还未更新时,dp[j]还记录着前i-1个物品在容量为j时的最大价值,这样就相当于还记录着dp[i-1][j]和dp[i-1][j-vol[i]]+val[i]。
为什么要从v开始递减遍历?我举个例子,假设一个物品GG价值1000,体积为2,那么假设我们按【0…..v】这个顺序遍历,那么在j=2时,dp[2] = max(dp[2], dp[0]+1000),那么dp[2] = 1000,当j=4时,dp[4]=max(dp[4], dp[2]+1000), dp[4] = 2000,这时我们再思考一下,GG将被放进背包两次!!,如果我们逆序遍历,就可以避免这种结果。
http://blog.csdn.net/qq_33279781/article/details/52073519
[Description]
Many years ago , in Teddy’s hometownthere was a man who was called “Bone Collector”. This man like to collectvaries 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 ofcollecting
there are a lot of bones , obviously , different bone has differentvalue 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.
(1<=T<=200)
Followed by T cases , each case three lines , the first line contain two integerN ,W, (1<=N<=1000 , 1<=W<=1000 )representing
the number of bonesand the volume of his bag.
And the second line contain N integers representing the
value of each bone (1<=Vi<=100). The third line contain N integersrepresenting the volume of each bone (1<=Wi<=100).
[Output]
Print “#t ans” contains one integer perline representing
the maximum of the total value (this number will be less than231).
[Time Limit]
1 sec for C/C++, 2 sec for Java
[Sample Input]
1
5 10
1 2 3 4 5
5 4 3 2 1
[Sample Output]
#1 14
Analysis:
0/1 背包问题,逆序遍历
Answer:
#include <stdio.h>
#include <string.h>
#define MAXN 1002
#define SIZE 5005
#define rint register int
#define is_digit(c) ((c)>='0' && (c)<='9')
#define MAX(x,y) ((x)>(y)?(x):(y))
int Ans,N,W,f[MAXN];
int w[MAXN],v[MAXN];
char buf[SIZE];
void input(int x[])
{
rint i,j,k,c;
fgets(buf,sizeof(buf),stdin);
for (i=j=0;c=buf[i];i++) {
if (!is_digit(c)) continue;
for (k=0;is_digit(c=buf[i]);i++)
k=k*10+c-'0';
x[++j]=k;
}
}
int main(void)
{
rint i,j,t;int T;
setbuf(stdout,NULL);scanf("%d",&T);
for (t=1;t<=T;t++) {
scanf("%d %d",&N,&W);
fgets(buf,sizeof(buf),stdin);
input(v);input(w);
for (j=W;j>=0;j--) f[j]=0;
for (i=1;i<=N;i++)
for (j=W;j>=w[i];j--)
f[j]=MAX(f[j],f[j-w[i]]+v[i]);
printf("#%d %d\n",t,Ans=f[W]);
}
return 0;
}
看了一点背包理论,来做这个题,不知道为啥1维2维,提交了2维的代码后一直不能通过测试用例,才发现用2维和用1维的思路是不一样的。
二维还是用的顺序遍历,一维用的是逆序。
如何理解二维降一维呢?对于外层循环中的每一个i值,其实都是不需要记录的,在第i次循环时,所有的dp[0…v]都还未更新时,dp[j]还记录着前i-1个物品在容量为j时的最大价值,这样就相当于还记录着dp[i-1][j]和dp[i-1][j-vol[i]]+val[i]。
为什么要从v开始递减遍历?我举个例子,假设一个物品GG价值1000,体积为2,那么假设我们按【0…..v】这个顺序遍历,那么在j=2时,dp[2] = max(dp[2], dp[0]+1000),那么dp[2] = 1000,当j=4时,dp[4]=max(dp[4], dp[2]+1000), dp[4] = 2000,这时我们再思考一下,GG将被放进背包两次!!,如果我们逆序遍历,就可以避免这种结果。
http://blog.csdn.net/qq_33279781/article/details/52073519
相关文章推荐
- 【Algothrim】 动态规划实例 (数字三角形问题)
- 【Algothrim】动态规划实例四(Business investment)
- 【Algothrim】 动态规划实例 (Piggy-Bank)
- 【Algothrim】动态规划实例 (Scores of marbles )
- 【Algothrim】 动态规划实例(Stamps)
- 【Algothrim】动态规划实例(0、1背包问题)
- 【Algothrim】动态规划实例(最长不下降子序列)
- 【Algothrim】 动态规划实例(最长公共子序列)
- 【Algothrim】动态规划实例 (Giving Coins for Candies)
- 【Algothrim】动态规划实例三(Domino Tiling )
- 【Algothrim】动态规划实例 (PC Assemble)
- 【Algothrim】Dijkstra 实例一
- c++使用动态规划dp(自底向上)重构解决钢条切割输出最大收益和切割方案及运行实例结果
- 趣学算法系列-动态规划-实例分析
- c++使用动态规划dp(自底向上)重构解决钢条切割输出最大收益和切割方案及运行实例结果
- 【Algothrim】动态规划法实例2
- 动态规划 ( DP ) 和 实例分析
- c++使用动态规划dp(自底向上)重构解决钢条切割输出最大收益和切割方案及运行实例结果
- Java矩阵连乘问题(动态规划)算法实例分析
- 【Algorithm】动态规划实例五 Making N Dollars