zoukankan      html  css  js  c++  java
  • OpenJudge 4120 硬币

    总时间限制: 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
    ", count);
            if (count == 0)
                printf("
    
    ");
            else
            {
                for (int i = 0; i < count; i++)
                {
                    if (i != count - 1)
                        printf("%d ", b[i]);
                    else
                        printf("%d
    ", b[i]);
                }
            }
    
        }
    }
  • 相关阅读:
    minGw编译器记录
    也来小谈jsonP
    [struts2]2.3.14 jsonplugin 存在bug<java.lang.NoSuchFieldException: DEFAULT_PARAM>
    年学习进度简记【2012】
    征服ExtJs那棵树(ExtJs官方开发手册汉语详解TreePanel)
    html 和ExtJs 搭建背景音乐 开发
    复习整理2
    MSChartHelpe
    DataToExcel
    如何将一个类型在FOREACH中使用
  • 原文地址:https://www.cnblogs.com/yun-an/p/10964233.html
Copyright © 2011-2022 走看看