user-0 提问: C语言：这个采药问题的算法有什么问题吗？

回复:
user: user-1
content: 昨天ls回复错了  昨天下班路上又想了一下，这是一个背包问题，0-1背包问题  重新给一个算法：  先给推理过程： 我们假设： si：第i株药草的采摘时间 wi：第i株药草的价值 W(i, t) 为：在总时间t内，采摘前i株药草（药草下标从1开始，前0株表示没有药草）所能获得的最大价值 则： 1、W(0, t) = 0 2、W(i, 0) = 0 3、若第i株药草的采摘时间si > t，则W(i, t) = W(i - 1, t) 4、若第i株药草的采摘时间si <= t，则W(i, t) = max( (wi + W(i - 1, t - si )), W(i - 1, t) )  说明： 1、无论总时间多少，无药可采时，所能获得的最大价值为0 2、无论有多少药可采，总时间为0时，所能获得的最大价值为0 3、若第i株草药的采摘时间超过总时间，那么该草药在当前总时间范围以内，无法被采摘： 则前i株草药所能产生的最大价值 = 前（i-1）株草药在总时间内所能产生的最大价值 4、若第i株草药的采摘时间不超过总时间，那么前i株草药所能产生的最大价值为： 要么采摘第i株草药，最大价值 = 第i株草药的价值 + 扣除第i株草药的时间后，用剩余时间去采摘前（i-1）株草药能产生的最大价值 要么不采摘第i株草药，最大价值 = 前（i-1）株草药在总时间内所能产生的最大价值 取以上两者的最大值  修改一下之前的代码  #include <iostream>  // 总时间T unsigned int T = 0; // 总草药数量M unsigned int M = 0; // M株草药的采摘时间和对应价值数组 unsigned int *second; unsigned int *worth; // 用于保存中间计算过程的推导数组（以一维数组的形式表示的二维数组） unsigned int *temp;  // 当总时间为limitSec时，前index株草药所能产生的最大价值 int FindMaxWorth(unsigned int index, unsigned int limitSec) { 	if (0 == index) 	{ 		// FindMaxWorth(0, limitSec) = 0 		// 无论总时间多少，无药可采时，所能获得的最大价值为0 		return 0; 	} 	else if (0 == limitSec) 	{ 		// FindMaxWorth(index, 0) = 0 		// 无论有多少药可采，总时间为0时，所能获得的最大价值为0 		return 0; 	} 	else 	{ 		if (second[index] > limitSec) 		{ 			// 若第index株草药的采摘时间超过总时间，那么该草药在当前总时间范围以内，无法被采摘： 			// 则前index株草药所能产生的最大价值 = 前（index-1）株草药在总时间内所能产生的最大价值 			// 则FindMaxWorth(index, limitSec) = FindMaxWorth(index - 1, limitSec) 			return temp[(index - 1) * T + limitSec]; 		} 		else 		{ 			// 若第index株草药的采摘时间不超过总时间，那么前index株草药所能产生的最大价值为： 			// 要么采摘第index株草药，最大价值 = 第index株草药的价值 + 扣除第index株草药的时间后，用剩余时间去采摘前（index-1）株草药能产生的最大价值 			// 要么不采摘第index株草药，最大价值 = 前（index-1）株草药在总时间内所能产生的最大价值 			// FindMaxWorth(index, limitSec) = worth[index] + FindMaxWorth(index - 1, limitSec - second[index]) 			// FindMaxWorth(index, limitSec) = FindMaxWorth(index - 1, limitSec) 			// 取以上两者的最大值 			unsigned int w1 = worth[index] + temp[(index - 1) * T + (limitSec - second[index])]; 			unsigned int w2 = temp[(index - 1) * T + limitSec]; 			return w1 > w2 ? w1 : w2; 		} 	} }  int main(int argc, char* argv[]) { 	T = 0; 	M = 0; 	std::cout << "enter T M:" << std::endl; 	std::cin >> T >> M; 	T = T + 1; // 时间下标从0开始，+1 	M = M + 1; // 草药下标从0开始，+1 	second = new unsigned int[M]; 	worth = new unsigned int[M]; 	temp = new unsigned int[M * T]; 	if (NULL != second && NULL != worth && NULL != temp) 	{ 		second[0] = 0; 		worth[0] = 0; 		for (unsigned int i = 1; i <= M; i++) 		{ 			std::cout << "enter second[" << i << "] worth[" << i << "]:" << std::endl; 			std::cin >> second[i] >> worth[i]; 		}  		// 推导 总时间为i，草药数量为j 时，能产生的最大价值 		for (unsigned int i = 0; i <= T; i++) 		{ 			for (unsigned int j = 0; j <= M; j++) 			{ 				temp[j * T + i] = FindMaxWorth(j, i); 			} 		}  		// 最后一个元素即为 总时间为T，草药数量为M 时的最终解 		std::cout << temp[M * T - 1] << std::endl; 	}  	if (NULL != second) 	{ 		delete[] second; 	} 	if (NULL != worth) 	{ 		delete[] worth; 	} 	if (NULL != temp) 	{ 		delete[] temp; 	}  	system("pause");  	return 0; }

user: user-1
content: 这题的算法：  步骤1、 找出M株药草中，在有限时间内，可以采摘的单位价值（价值/时间）最高的那一株药草  步骤2、 总时间T，扣除该株药草所需时间，该株药草的价值清零（按题意应该是1株药草只能采摘1次，不可重复采摘）  然后继续步骤1，直到找不到药草（即所有药草全部采摘完毕，或剩余时间不足以再次采摘）为止。   #include <iostream>  // 总时间T unsigned int T = 0; // 总药草数量M unsigned int M = 0; // M株药草的采摘时间和对应价值数组 unsigned int *second; unsigned int *worth;  // 找出M株药草中，在有限时间内，可以采摘的单位价值（价值/时间）最高的那一株药草 int FindMaxWorth(unsigned int limitSec) { 	float maxWorth = 0.0f; 	int maxIndex = -1; 	for (unsigned int i = 0; i < M; i++) 	{ 		if (0 < second[i] && second[i] <= limitSec) 		{ 			if ((1.0f * worth[i] / second[i]) > maxWorth) 			{ 				maxWorth = 1.0f * worth[i] / second[i]; 				maxIndex = i; 			} 		} 	}  	return maxIndex; }  int main(int argc, char* argv[]) { 	T = 0; 	M = 0; 	std::cout << "enter T M:" << std::endl; 	std::cin >> T >> M; 	second = new unsigned int[M]; 	worth = new unsigned int[M]; 	if (NULL != second && NULL != worth) 	{ 		for (unsigned int i = 0; i < M; i++) 		{ 			std::cout << "enter second[" << i << "] worth[" << i << "]:" << std::endl; 			std::cin >> second[i] >> worth[i]; 		}  		unsigned int currWorth = 0;	// 已采摘的总价值 		unsigned int lastSecond = T;// 剩余时间 		int maxIndex = -1;			// 找到的单位价值（价值/时间）最高的药草下标 		while (true) 		{ 			maxIndex = FindMaxWorth(lastSecond); 			if (0 <= maxIndex) 			{ 				currWorth = currWorth + worth[maxIndex];		// 累积价值 				lastSecond = lastSecond - second[maxIndex];		// 扣除剩余时间 				worth[maxIndex] = 0;							// 被采摘的药草价值清零 			} 			else 			{ 				break; 			} 		}  		std::cout << currWorth << std::endl; 	}  	if (NULL != second) 	{ 		delete[] second; 	} 	if (NULL != worth) 	{ 		delete[] worth; 	}  	system("pause");  	return 0; }   代码是C++的，输入是控制台输入的，lz自行修改为输入读文件即可

user: user-2
content: #include <stdio.h>  int total_time, medics; int value[100]; int time[100]; int max[1001];  int main() {     int i, t;      printf("Please input total time and medics: ");     scanf("%d%d", &total_time, &medics);      for (i = 0; i < medics; i++) {         scanf("%d%d", &time[i], &value[i]);     }      for (i = 0; i < medics; i++)         for ( t = total_time; t > 0; t--)             if (time[i] <= t)                 if (value[i] + max[t-time[i]] > max[t])//第i个的价值+不选第i个且用时为t-time[i-1]时最大价值                     max[t] = value[i] + max[t-time[i]];      printf("%d\n", max[total_time]);      return 0; } 作为一个参考～

user: user-0
content: 那里确实有问题，但改完还有问题。 Result: Wrong Answer     Memory Used: 824 KB     Time Used: 0 ms  Language: GNU C     Username:      Problem ID:   Copy #include <stdio.h> int main(void) {     int T, M;     while(scanf("%d %d", &T, &M) == 2){         int t[M],val[M];         int output = 0;         for(int i = 0;i < M;i++)             scanf("%d %d",t+i, val+i);         int max[M][T+1];         for(int j = 0;j <= T;j++){             for(int i = 0;i < M;i++){                 if(!i)                 {                     max[i][j] = (j < t[i])?0 : val[i];                 }                 else{                     max[i][j] = (j < t[i])?max[i-1][j] : max[i-1][j-t[i]]+val[i];                 }          //       printf("i:%d j:%d ----->%d\n", i, j, max[i][j]);         }         }         for(int i = 0;i < M;i++)             output = (output > max[i][T]) ? output : max[i][T];         printf("%d\n", output);     }     return 0; }

user: user-3
content: 不应该赋值为0啊，赋值 max[i-1][j-1]

user: user-0
content: 中间那个printf();是我自己用来测试的