题目链接

题意 : 给出一些固定面值的硬币的数量、再给你一个总金额、问你最多能用多少硬币来刚好凑够这个金额、硬币数量和总金额都很大

 

分析 :

长春赛区的金牌题目

一开始认为除了做类似背包DP那样子的DP外、别无他法

时空限制下是不可能DP的

众所周知背包DP问题贪心是错的

遂认定不是贪心方向

看到题解、真香~

这种凑硬币问题、如果满足一个条件、那么贪心是正确的

当然和这道题目不一样、可贪心的是要求用最少的硬币凑出总金额

需要满足的条件是、可选择的硬币面额满足大面额是小面额的倍数

如果不满足上述条件?

那么用经典的 dp[i][j] = dp[i-1][j-w[i]] + 1 就能解决

当然指的是数据并不是很大的情况下、dp 复杂度在时空限制之内

那么如果满足上述条件呢?

直接贪心即可

从大往小一直选、能凑出就肯定是用硬量最少的、不能则不行

为什么这样子的贪心是对的呢?

首先要明白满足红字条件下一个很重要的性质

大面额硬币能够凑到的金额、因为是倍数关系、所以小面额的硬币也铁定能凑到

那能用大面额凑到的、就肯定不用小面额

比如 20 20 20 60 凑 60 这个数据、能直接用 60 凑够、那就不必用 20+20+20 了

那来一个不满足上述条件的例子 10 20 50 凑 60、从大到小、会先凑出 70、这样子又要回溯回去

类似一个 DFS 的过程、所以这样子贪心肯定是不行的、变成搜索了?

故需要满足大面额是小面额的倍数才行

还有一个很傻逼的问题、我之前还在想

如果满足了这个倍数关系条件、但是问题是要你凑最多的能用多少硬币、能不能直接贪心?

显然只有我这种蒟蒻才能提这种问题、显然不行、因为到后面还剩的硬币是大面额的、不灵活了

好了、那么回到这道题本身

问题是凑最多的硬币、直接贪不行怎么办?

那就间接贪、假设要凑出来的数目是 p 、你拥有的硬币的总额是 tot

那么你只要用最少的硬币凑出 tot - p 是不是剩下的就是最多的能凑出 p 的硬币

但是问题来了、这道题有并不是倍数关系的两组关系

20 和 50 、 200 和 500 、不满足条件了、怎么办?

如果这种关系比较少、例如这题只有两组、那么就想办法让它再次满足倍数关系

这题的方法是、枚举 50 和 500 选取的数量的奇偶性、什么意思?

枚举是否固定先选择一个 50 或者 500、然后后面的贪心过程

50 和 500 都是成对选、这样子就相当于有面额分别为 100 和 1000 、权重是 2 的硬币

那为什么这样子又是对的呢?

因为如果你凑的硬币中包含了 50 或者 500

那么其数量非奇即偶、对于偶数情况就是满足上述贪心性质相当于有面额分别为 100 和 1000 、权重是 2 的硬币

但是如果有奇数的话、那么你就提前选了、就是你让 p 提前选一个 50 或者 500 、即现在要凑 p-50 .....

这样子你后面成对枚举 50 和 500 、也就能保证 50 和 500 的数量是奇数了、挺巧妙的

那么这题就解决了、枚举 50 和 500 奇偶、然后每次 O(n)贪心

 #include<bits/stdc++.h>
#define LL long long
#define ULL unsigned long long

#define scl(i) scanf("%lld", &i)
#define scll(i, j) scanf("%lld %lld", &i, &j)
#define sclll(i, j, k) scanf("%lld %lld %lld", &i, &j, &k)
#define scllll(i, j, k, l) scanf("%lld %lld %lld %lld", &i, &j, &k, &l)

#define scs(i) scanf("%s", i)
#define sci(i) scanf("%d", &i)
#define scd(i) scanf("%lf", &i)
#define scIl(i) scanf("%I64d", &i)
#define scii(i, j) scanf("%d %d", &i, &j)
#define scdd(i, j) scanf("%lf %lf", &i, &j)
#define scIll(i, j) scanf("%I64d %I64d", &i, &j)
#define sciii(i, j, k) scanf("%d %d %d", &i, &j, &k)
#define scddd(i, j, k) scanf("%lf %lf %lf", &i, &j, &k)
#define scIlll(i, j, k) scanf("%I64d %I64d %I64d", &i, &j, &k)
#define sciiii(i, j, k, l) scanf("%d %d %d %d", &i, &j, &k, &l)
#define scdddd(i, j, k, l) scanf("%lf %lf %lf %lf", &i, &j, &k, &l)
#define scIllll(i, j, k, l) scanf("%I64d %I64d %I64d %I64d", &i, &j, &k, &l)

#define lson l, m, rt<<1
#define rson m+1, r, rt<<1|1
#define lowbit(i) (i & (-i))
#define mem(i, j) memset(i, j, sizeof(i))

#define fir first
#define sec second
#define VI vector<int>
#define ins(i) insert(i)
#define pb(i) push_back(i)
#define pii pair<int, int>
#define VL vector<long long>
#define mk(i, j) make_pair(i, j)
#define all(i) i.begin(), i.end()
#define pll pair<long long, long long>

#define _TIME 0
#define _INPUT 0
#define _OUTPUT 0
clock_t START, END;
void __stTIME();
void __enTIME();
void __IOPUT();
using namespace std;

);
;

LL c[] = {, , , , , , , , , , };
LL num[maxn], tmpNum[maxn], tot;
LL sum, tmpSum;
LL p;

LL Cal(LL n)
{
    LL ret = ;
    ; i>=; i--){
         || i == ){
            ret +=  * min(tmpNum[i]/, n/(c[i]*));
            n -=  * c[i] * min(tmpNum[i]/, n/(c[i]*));
        }else{
            ret += min(tmpNum[i], n / c[i]),
            n -= c[i] * min(tmpNum[i], n / c[i]);
        }
        ) return ret;
    }
    return INF;
}

int main(void){__stTIME();__IOPUT();

    int nCase;
    sci(nCase);

    while(nCase--){

        scl(p);

        sum = tot = 0LL;

        ; i<=; i++){
            scl(num[i]);
            sum += num[i] * c[i];
            tot += num[i];
        }

        if(sum < p) { puts("-1"); continue; }

        LL mm = INF;
        ; _50<=; _50++){
            ; _500<=; _500++){

                ; i<=; i++)
                    tmpNum[i] = num[i];
                tmpSum = sum;

                if(_50){
                    ] > ) tmpSum -= , tmpNum[]--;
                    else continue;
                }

                if(_500){
                    ] > ) tmpSum -= , tmpNum[]--;
                    else continue;
                }

                ) mm = min(mm, Cal(tmpSum - p) + _50 + _500);
            }
        }

        if(mm >= INF) puts("-1");
        else printf("%lld\n", tot - mm);
    }

__enTIME();;}

void __stTIME()
{
    #if _TIME
        START = clock();
    #endif
}

void __enTIME()
{
    #if _TIME
        END = clock();
        cerr<<"execute time = "<<(double)(END-START)/CLOCKS_PER_SEC<<endl;
    #endif
}

void __IOPUT()
{
    #if _INPUT
        freopen("in.txt", "r", stdin);
    #endif
    #if _OUTPUT
        freopen("out.txt", "w", stdout);
    #endif
}

HDU 5527 Too Rich ( 15长春区域赛 A 、可贪心的凑硬币问题 )的更多相关文章

  1. HDU 4816 Bathysphere (2013长春现场赛D题)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4816 2013长春区域赛的D题. 很简单的几何题,就是给了一条折线. 然后一个矩形窗去截取一部分,求最 ...

  2. 2015年ACM长春区域赛比赛感悟

    距离长春区域赛结束已经4天了,是时候整理一下这次比赛的点点滴滴了. 也是在比赛前一周才得到通知要我参加长春区域赛,当时也是既兴奋又感到有很大的压力,毕竟我的第一场比赛就是区域赛水平,还是很有挑战性的. ...

  3. HDU 4768 Flyer (2013长春网络赛1010题,二分)

    Flyer Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submi ...

  4. HDU 4818 RP problem (高斯消元, 2013年长春区域赛F题)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4818 深深地补一个坑~~~ 现场赛坑在这题了,TAT.... 今天把代码改了下,过掉了,TAT 很明显 ...

  5. Travel(HDU 5441 2015长春区域赛 带权并查集)

    Travel Time Limit: 1500/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)Total Su ...

  6. 2015ACM/ICPC亚洲区长春站 A hdu 5527 Too Rich

    Too Rich Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)Total ...

  7. hdu 5538 House Building(长春现场赛——水题)

    题目链接:acm.hdu.edu.cn/showproblem.php?pid=5538 House Building Time Limit: 2000/1000 MS (Java/Others)   ...

  8. HDU 5527 Too Rich

    Too Rich Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)Total ...

  9. Hdu 5439 Aggregated Counting (2015长春网络赛 ACM/ICPC Asia Regional Changchun Online 找规律)

    题目链接: Hdu 5439 Aggregated Counting 题目描述: 刚开始给一个1,序列a是由a[i]个i组成,最后1就变成了1,2,2,3,3,4,4,4,5,5,5.......,最 ...

随机推荐

  1. BridgeOverARoughRiver(POJ-3404)【AdHoc】

    题目链接:https://vjudge.net/problem/POJ-3404 题意:n个极限速度不同的人要过桥,一开始所有人在桥的一边,每次最多两个人同时过桥,过桥时需要用一把火炬并且全场只有一把 ...

  2. python 基础(十七)--hashlib加密模块

    hashlib加密模块 两种方式使用 字符串是中文时需要先编码成utf-8 常用加密算法:md5,sha1(已被破解)等... >>> a= hashlib.md5() >&g ...

  3. Python内存相关

    Python内存相关 示例一: v1 = [1, 2, 3] v2 = [1, 2 ,3] v1 = 123 v2 = 123 v1 = "dogfa" v2 = "do ...

  4. 这里除了安全,什么都不会发生!Docker镜像P2P加速之路

    1.1      问题: 在使用Docker运行容器化应用时,宿主机通常先要从Registry服务(如Docker Hub)下载相应的镜像(image).这种镜像机制在开发环境中使用还是很有效的,团队 ...

  5. Docker 容器学习笔记

    Docker 诞生于2013年,最初发起者是dotCloud公司.Docker自开源后受到广泛的关注和讨论,目前已有多个相关项目逐渐形成了围绕Docker容器的生态体系,由于Docker在业界造成的影 ...

  6. MySQL SELECT语法(四)UNION语法详解

    源自MySQL 5.7 官方手册:13.2.9.3 UNION Syntax 一.UNION语法 UNION用于将多个SELECT语句的结果合并到一个结果集中. SELECT ... UNION [A ...

  7. 怎样理解Canvas

    Canvas 是一种在网页中的画布, 是一个HTML5新增的标签, 是一种高效的绘制图形的技术, 在JavaScript中有一个专门的API用于给他赋能( CanvasRenderingContext ...

  8. sqlce基本语法

    整理和总结一下SQLCE的用法引用  System.Data.SqlServerCe(1)数据库文件的创建     SqlCeEngine eng = new SqlCeEngine("Da ...

  9. vue项目中导出PDF的两种方式

    参考大家导出的方式,基本上是如下两种: 1.使用 html2Canvas + jsPDF 导出PDF, 这种方式什么都好,就是下载的pdf太模糊了.对要求好的pdf这种方式真是不行啊! 2.调用浏览器 ...

  10. CentOS7 PHP增加连接Sqlserver扩展

    扩展插件下载地址 https://github.com/Microsoft/msphpsql/tags 本机PHP版本7.2,非线程安全 https://github.com/microsoft/ms ...