ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

[PAT-A 1068]Find More Coins

2020-03-07 20:03:23  阅读:315  来源: 互联网

标签:1068 PAT 硬币 int Coins choice maxn 数组 dp


在这里插入图片描述
题目大意:
有N枚硬币,给出每枚硬币的价值,现在要用这些硬币去支付价值为M的东西。
问是否可以找见这样的方案,使得选择用来支付的硬币价值之和恰好为M,如果不存在,输出NoSolution。
如果存在,从小到大输出选择用来支付硬币的价值,如果有多种方案,则输出字典序最小的那个。

思路:
题目中的价值c[i]与质量w[i]是等价的,可以把c[i]与w[i]使用一个数组存放。
由于题目要求以价值从小到大的顺序输出,因此需要先把数组从小到大排序,然后再进行正常的01背包的dp操作。
状态转移方程dp[i][v]=max{dp[i-1][v],dp[i-1][v-w[i]]+c[i]}.
在此基础上开设一个二维数组choice[i-1][v],用来计算dp[i][v]时是选择了哪个策略。
如果状态转移时选择了dp[i-1][v]则choice[i][v]=0,表示不放第i件物品。
如果在状态转移时选择了dp[i-1][v-w[i]]+c[i],则choice[i][v]=1,表示选择了第i件物品。
这样dp数组求解完之后,选择最大的dp[n][v],从第n件物品开始倒着查看每一件物品是否放入背包。

无解的条件为dp[n][m]!=m,因为题目要求恰好能付清价值为M的货币,因此只要dp[m]不是m就说明无解。
求解dp数组时,如果两个策略的大小相等,则应该选择放第i件物品的策略。

AC代码:

//PAT_A 1068
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn = 10010;
const int maxv = 110;
int w[maxn], dp[maxn][maxv] = { 0 };
bool choice[maxn][maxv], flag[maxn];
bool cmp(int a, int b) {
	return a > b;
}
int main() {
	int n, m;
	(void)scanf("%d %d", &n, &m);
	for (int i = 1; i <= n; i++) {
		(void)scanf("%d", &w[i]);
	}
	sort(w + 1, w + n + 1, cmp);
	for (int i = 1; i <= n; i++) {
		for (int v = w[i]; v <= m; v++) {
			int temp1 = dp[i - 1][v - w[i]] + w[i];//放
			int temp2 = dp[i - 1][v];//不放
			if (temp1 >= temp2) {//保证字典序,如果相等也要选
				choice[i][v] = 1;//选i号硬币
				dp[i][v] = temp1;
			}
			else {
				choice[i][v] = 0;//不选i号硬币
				dp[i][v] = temp2;
			}
		}
	}
	if (dp[n][m] != m)printf("No Solution");
	else {
		int k = n, num = 0, v = m;//看choice数组的第v列
		while (k >= 0) {
			if (choice[k][v] == 1) {
				flag[k] = true;
				v -= w[k];
				num++;
			}
			else flag[k] = false;
			k--;
		}
		for (int i = n; i >= 1; i--) {
			if (flag[i] == true) {
				printf("%d", w[i]);
				num--;
				if (num > 0)printf(" ");
			}
		}
	}
	return 0;
}

标签:1068,PAT,硬币,int,Coins,choice,maxn,数组,dp
来源: https://blog.csdn.net/weixin_44699689/article/details/104719162

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有