HDU 2602 Bone Collector (简单的0-1背包)(AC)

Bone Collector

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 24860    Accepted Submission(s): 10062


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 ?

 

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.
 

Output
One integer per line representing the maximum of the total value (this number will be less than 2 31).
 

Sample Input
  
  
1 5 10 1 2 3 4 5 5 4 3 2 1
 

Sample Output
  
  
14
#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>

//第一次提交WA
//后来看了discuss,原来是还可以骨头没重量但是有价值的,但是还是WA,这其实真的是一道很基本的DP0-1背包问题

//这个就是最基本的0-1背包问题,拿或不拿
#define MAXX 1005
int map[MAXX];
int value[MAXX];
int ans[MAXX];
int visit[MAXX]; //这个是否拿了,表示第几个物体已经被拿了
int N = 0;
int V = 0;
int maxindex = 0;

void init()
{
	int i = 0;
	for (i = 0; i <= MAXX; i++) //i要从0开始啊,怎么能从1开始啊,竟然还犯这样的错误啊,不应该啊
	{
		map[i]   = 0;
		value[i] = 0;
		ans[i]   = 0;
		visit[i] = 0;
	}
	N = 0;
	V = 0;
	maxindex = 0;
	return;
}

int max(int a, int b)
{
	if (a < b)
	{
		//printf("4--a = %d,b = %d,maxindex = %d\n", a, b, maxindex);
		return b;
	}
	else
	{		
		return a;
	}
}


//一维数组AC
void dp()
{
	int i        = 0;
	int j        = 0;
	//自己写的犯了2个问题,1:应该是用物体个数做主循环,2:而且如果是用一维数组,V应该是从v-0这个顺序开始
	//dp没什么visit这样的标志
#if 0
	for (i = 0; i <= V;i++) //背包的重量,自己是从2开始的,但是我前面0,1都有涉及的
	{
		maxindex = 0;
		//ans[i] = ans[i-1]; //这个很关键,自己一直没写对,这个很关键,这个值的初始值应该是前一个值,然后做比较
		for (j = 1; j <= N;j++)
		{
			if (visit[j]) continue;
			//printf("1--%d - %d = %d\n", i, map[j], i - map[j]);
			if ((i-map[j]) >=0)
			{
				//printf("2--tmpans[%d] = %d,after= %d, value[%d] = %d\n", i, ans[i], ans[i - map[j]] + value[j], j, value[j]);
				ans[i] = max((ans[i - map[j]] + value[j]), ans[i],j); //反复循环新的值和ans[i]比较,直到找到ans[i]的最大值
				//别人的背包都不用加visit这些东西来标记的。。。自己的思想其实是应该用二维数组来表示的,不是所有的都要用1维表示的

			}			
		}

		//printf("3--ans[%d] = %d,maxindex = %d\n", i, ans[i], maxindex);
		visit[maxindex] = 1;
	}
#endif
	for (i = 1; i <= N;i++)
	{
		for (j = V; j >= 0;j--) //逆序 当内循环是逆序时,就可以保证后一个f[v]和f[v-c[i]]+w[i]是前一状态的!
		{
			if ((j - map[i])<0) continue; //这个不能忘
			ans[j] = max((ans[j - map[i]] + value[i]), ans[j]);
		}
	}
	return;
}

int main()
{
	int i = 0;
	int j = 0;
	int T = 0;
	int sum = 0;
	freopen("input.txt","r",stdin);
	scanf("%d",&T);
	for (i = 1; i <= T;i++)
	{
		//printf("111:%d\n", ans[0]);
		init();
		//printf("222:%d\n", ans[0]);
		//sum = 0;
		scanf("%d %d", &N, &V);
		//printf("333:%d\n", ans[0]);
		for (j = 1; j <= N;j++)
		{
			scanf("%d", &value[j]);
		}

		for (j = 1; j <= N; j++)
		{
			scanf("%d", &map[j]);	
#if 0
			if (0 == map[j])
			{
				sum += value[j];
			}
			if (1 == map[j])
			{
				ans[1]   = value[j]; //V=1的时候最大值肯定就是体积是1的价值
				visit[j] = 1;
			}
#endif
		}
#if 0
		if (0 == V)
		{
			printf("%d\n", sum);
			continue;
		}



		if (1 == V)
		{
			printf("%d\n", sum + ans[1]);
			continue;
		}

#endif
		dp();
		//还有一种方法是用二维数组的dp[i][v]=max{dp[i-1][v],dp[i-1][v-cost[i]]+value[i]}
		printf("%d\n",ans[V]);
	}

	return 0;
}


 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值