题目
题目描述
Eva loves
to collect coins
from all over
the universe, including some other planets like Mars. One day she visited
a universal shopping mall which could accept all kinds
of coins
as payments. However, there was
a special requirement
of the payment:
for each bill, she must pay
the exact amount. Since she has
as many
as 104 coins
with her, she definitely needs your help. You are supposed
to tell her,
for any given amount
of money, whether
or not she can find some coins
to pay
for it.
输入描述:
Each input
file contains one test
case. For
each case,
the first line contains 2 positive numbers: N (<=
104,
the total
number of coins)
and M(<=
102,
the amount
of money Eva has
to pay). The
second line contains N face values
of the coins, which are all positive numbers. All
the numbers
in a line are separated
by a space.
输出描述:
For
each test
case, print
in one line the face values V1 <= V2 <= ... <= Vk such that V1 + V2 + ... + Vk = M. All
the numbers must be separated
by a space,
and there must be no extra
space at the end of the line. If such a solution is not unique, output the smallest sequence. If there is no solution, output "No Solution" instead.
Note: sequence {A[
1], A[
2], ...} is said
to be
"smaller" than sequence {B[
1], B[
2], ...}
if there exists k >=
1 such that A[i]=B[i]
for all i < k,
and A[k] < B[k].
输入例子:
8 9
5 9 8 7 2 3 4 1
输出例子:
1 3 5
思路
1.看了别人的代码,说是典型的背包问题,但是背包问题也不知道是啥啊,然后看背包问题,说要用动态规划,然后这个也不知道啊,所以这些参考我的这篇博客吧。网址:2.动态规划感觉总结就是从小的结构到大的结构构造出一张表,然后利用这个表慢慢推出大的结构,从而避免小的结构要算很多次了。3.这里也是构造一个findmax_I_J,表示从前i个值中(即已经排好序的给出的那一行数据,至于为什么排序后面讲)可以找到的不大于j的最大值(小于或者等于j都可以),这样我们最后通过判断findmax_N_M==M,即在这n个数中,能找到的不大于m的最大值为m,就表示有解。4.怎么构造findmax_I_J呢,把每一个findmax_I_J分为不要a[I]和需要它的俩部分,例如,对于数列a[]: 9 8 7 5 4 3 2 1,求findmax_2_9,即在前俩个数中,找出的组合成不大于9的数的最大数是多少?(组合是指前俩个数都可以选择要还是不要即有4中选择),很显然,这个数是9(要求不能大于9,所以不能全加起来),并且不需要第二个数8!!5.一般的,findmax_I_J有公式: findmax_I_J=max{findmax_(I-1)_(J-a[I])+a[I],findmax_(I-1)_J}即取需要a[I]和不需要a[I]俩种情况的最大值作为他的最大值,还看不懂就去看我讲的简谈动态规划:。6.题目要你优先输出较小的数,这个就是为什么要先排序的原因了,这里是从大到小,从后面开始往前输出就解决了,具体怎么做的看代码。7.最后就是输出问题了,用flag保存findmax_I_J取最大值时需不需要I,然后倒序输出就可以了。
我出错的一些点
1.sort(a + 1, a + 1 + n,greater<int>());2.//这个要放在main函数之前 不知道为啥 int findmax_I_J[10005][105], flag[10005][105], a[10005];3.//即如果flag[n][m]不需要n,n就-- while (flag[n][m] != 1)n--;
代码
#include<iostream>
#include<algorithm>
#include<vector>
#include<functional>
using namespace std;
int findmax_I_J[
10005][
105], flag[
10005][
105], a[
10005];
int main()
{
int n, m;
cin >> n >> m;
for (
int i =
1; i <= n; i++)
{
cin >> a[i];
}
sort(a +
1, a +
1 + n,greater<
int>());
for (
int i =
1; i <= n; i++)
{
for (
int j =
0; j <= m; j++)
{
flag[i][j] =
0;
if (findmax_I_J[i-
1][j-a[i]]+a[i]<findmax_I_J[i-
1][j]||a[i]>j)
{
findmax_I_J[i][j] = findmax_I_J[i -
1][j];
}
else
{
findmax_I_J[i][j] = findmax_I_J[i -
1][j - a[i]] + a[i];
flag[i][j] =
1;
}
}
}
vector<int> b;
if (findmax_I_J[n][m]==m)
{
while (m)
{
while (flag[n][m] !=
1)n--;
b.push_back(a[n]);
m -= a[n--];
}
for (
int i =
0; i < (
int)(b.size()); i++)
{
if (i==
0)
cout << b[i];
else
cout <<
" " << b[i];
}
cout << endl;
}
else
{
cout <<
"No solution" << endl;
}
return 0;
}
转载请注明原文地址: https://ju.6miu.com/read-1308028.html