您的位置:首页 > 编程语言 > Go语言

【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


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: