PAT 1026 Find More Coins (30)

题目

题目描述
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;
//这个要放在main函数之前 不知道为啥
//findmax_I_J表示从前i个可以找到的不大于j的最大值(小于或者等于j都可以)
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>());
    //findmax_I_J[0][m] = 0;
    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)
        {
            //即如果flag[n][m]不需要n,n就--
            while (flag[n][m] != 1)n--;
            b.push_back(a[n]);
            //即在n-1,m-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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值