PAT 甲级 1068 Find More Coins

题意:小红想收集一定数额的金币,在给定的一些金币中,选择总的面额等于给定的面额,而且要求这个金币的面额是最小。

思路:01背包思想,此题没有考虑另外一种变量的要求,只有金币限额的要求,对于当前面额的金币有两种情况,如果超过了当前的面额,则当前面额是等于i-1的面额的,如果当前面额小于总的所需面额,需要判断选择了当前面额的金币是否能达到最优解即max(dp[i-1],dp[i-1]+w[i]),对于此题,只涉及了一维的量,在查找的时候只需判断当前的金币收藏之后是否比前面的更优此情况,最后找到最优解后就从所需面额回溯开始遍历,找到所有构成的金币。

对于01背包,自认为此文讲的很好:https://blog.csdn.net/qq_38410730/article/details/81667885

代码:

#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
int dp[10010] = { 0 }, w[10010] = {0};
bool chioce[10010][110];//用于判断该点是否被选中
int main() {
	int n, m;
	cin >> n >> m;
	for (int i = 1; i <= n; i++) {//输入所有金币的面额
		scanf("%d",&w[i]);
	}
	sort(w + 1, w + n + 1, greater<int>());//按照从大到小的顺序排序
	for (int i = 1; i <= n; i++) {//从第一个商品开始遍历,寻找最优解
		for (int j = m; j >= w[i]; j--) {
			if (dp[j] <= dp[j - w[i]] + w[i]) {//如果加入当前i的商品后更优,则替换
				chioce[i][j] = 1;
				dp[j] = dp[j - w[i]] + w[i];
			}
		}
	}
	if (dp[m] != m) printf("No Solution\n");
	else {
		vector<int> ans;
		int index = n, p = m;
		while (p > 0) {
			if (chioce[index][p] == true) {
				ans.push_back(w[index]);
				p -= w[index];
			}
			index--;
		}
		for (int i = 0; i < ans.size(); i++) {
			printf("%d%s", ans[i], i == ans.size() - 1 ? "\n" : " ");
		}
	}
	system("pause");
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值