01揹包(打印路徑) 之 uva 624

//  [7/21/2014 Sjm]
/*
此題直接根據01揹包的求解思路,記錄路徑,再遞歸輸出。。1A。。
注:
對於最後一個測試用例 43 2 也是滿足題目要求的,輸出它也是對的。
*/
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
const int MAX_NUM = 25;
const int MAX_N = 100005;
struct node {
	int t_n; // 得到它前面那個所取節點的位置
	bool Judge;  // 判斷當前節點是否被選擇
};
int N, num;
int dp[MAX_NUM][MAX_N], arr[MAX_NUM];
node vis[MAX_NUM][MAX_N];

void output(int mynum, int myN, int sum) {
	if (sum == 0) {
		return;
	}
	if (vis[mynum][myN].Judge) {
		output(mynum - 1, vis[mynum][myN].t_n, sum - arr[mynum]);
		printf("%d ", arr[mynum]);
	}
	else {
		output(mynum - 1, myN, sum);
	}
}

void Solve() {
	for (int i = 1; i <= num; ++i) {
		for (int k = 0; k < arr[i]; ++k) {
			dp[i][k] = dp[i - 1][k];
		}
		for (int j = arr[i]; j <= N; ++j) {
			if (dp[i - 1][j - arr[i]] + arr[i] > dp[i - 1][j]) {
				dp[i][j] = dp[i - 1][j - arr[i]] + arr[i];
				vis[i][j].Judge = true;
				vis[i][j].t_n = j - arr[i];
			}
			else { dp[i][j] = dp[i - 1][j]; }
		}
	}

	int start;
	for (start = num; start >= 0; --start) {
		if (vis[start][N].Judge) {
			break;
		}
	}
	output(start, N, dp[start][N]);

	printf("sum:%d\n", dp[num][N]);
}

int main()
{
	//freopen("input.txt", "r", stdin);
	while (~scanf("%d %d", &N, &num)) {
		for (int i = 0; i <= num; ++i) {
			for (int j = 0; j <= N; ++j) {
				dp[i][j] = 0;
				vis[i][j].Judge = false;
				vis[i][j].t_n = -1;
			}
		}
		for (int i = 1; i <= num; ++i) {
			scanf("%d", &arr[i]);
		}
		Solve();
	}
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章