首页 > 其他 > 详细

OpenJudge 4120 硬币

时间:2019-06-02 21:02:11      阅读:164      评论:0      收藏:0      [点我收藏+]

总时间限制: 1000ms 内存限制: 262144kB

描述

宇航员Bob有一天来到火星上,他有收集硬币的习惯。于是他将火星上所有面值的硬币都收集起来了,一共有n种,每种只有一个:面值分别为a1,a2… an。 Bob在机场看到了一个特别喜欢的礼物,想买来送给朋友Alice,这个礼物的价格是X元。Bob很想知道为了买这个礼物他的哪些硬币是必须被使用的,即Bob必须放弃收集好的哪些硬币种类。飞机场不提供找零,只接受恰好X元。

输入

第一行包含两个正整数n和x。(1 <= n <= 200, 1 <= x <= 10000)
第二行从小到大为n个正整数a1, a2, a3 … an (1 <= ai <= x)

输出

第一行是一个整数,即有多少种硬币是必须被使用的。
第二行是这些必须使用的硬币的面值(从小到大排列)。

样例输入

5 18
1 2 3 5 10

样例输出

2
5 10

提示

输入数据将保证给定面值的硬币中至少有一种组合能恰好能够支付X元。
如果不存在必须被使用的硬币,则第一行输出0,第二行输出空行。

容斥定理

计数时,必须注意没有重复,没有遗漏。为了使重叠部分不被重复计算,人们研究出一种新的计数方法,这种方法的基本思想是:先不考虑重叠的情况,把包含于某内容中的所有对象的数目先计算出来,然后再把计数时重复计算的数目排斥出去,使得计算的结果既无遗漏又无重复,这种计数的方法称为容斥原理。

简单来说,对于一种钱,如果没有它,还可以达到想要的钱,它就是不必须的,用01背包写。

AC代码

#include<stdio.h>
#include<string.h>
int dp[1000005];//表示形成i钱数的方案
int ans[1000005];//表示没有j时形成i钱数的方案数,如果方案数>0.那说明j不必要
int a[220];//存放钱的种类
int b[220];//存放必须有的钱币的种类
int main()
{
    int n, m;//钱的种类数和礼物价格
    int count, k;
    while (scanf("%d%d", &n, &m) != EOF)
    {
        for (int i = 1; i <= n; i++)
            scanf("%d", &a[i]);//读入钱币
        memset(dp, 0, sizeof(dp));//初始化dp,即价格为i时可用的方案数
        dp[0] = 1;//0元礼物的方案数为1
        for (int i = 1; i <= n; i++)
        {
            for (int j = m; j >= a[i]; j--)//逆序,典型的0-1背包
            {
                dp[j] = dp[j] + dp[j - a[i]];
                //j是由a[i]和j-a[i]的和,a[i]的方案为1,
                //j-a[i]的方案数为dp[j-a[i]];
            }
        }
        count = 0;
        for (int i = 1; i <= n; i++)
        {
            for (int j = 0; j <= m; j++)
            {
                if (j < a[i])
                    ans[j] = dp[j];
                else
                    ans[j] = dp[j] - ans[j - a[i]];
            }
            if (ans[m] == 0)//缺了j就不行了,那么j是必需的
            {
                b[count++] = a[i];
            }
        }
        printf("%d\n", count);
        if (count == 0)
            printf("\n\n");
        else
        {
            for (int i = 0; i < count; i++)
            {
                if (i != count - 1)
                    printf("%d ", b[i]);
                else
                    printf("%d\n", b[i]);
            }
        }

    }
}

 

OpenJudge 4120 硬币

原文:https://www.cnblogs.com/yun-an/p/10964233.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!