HDU 3348 By Assassin [可怕的模拟题]
2017-05-02 10:36
375 查看
题意
有1角,5角,1元,5元、十元的纸币,每种硬币现有总数已知,想要正好组合出p角,问最多最少分别用多少张纸币,如果不能组合成功,输出“-1 -1”.分析
思路是直接了当的,首先我们先求使用张数最小的情况,注意每种纸币需要判断现有的数量是否够用,如果最小值可以求的,那么最大值一定存在,否则输出-1 -1. 那么我们求得最小值的每种纸币的张数之后呢,我们想,如何让张数尽可能变多?100=50+50 50=10*5 10=5*2 5=1*5 .只要转换,就可实现张数的变多。还是注意每次注意判断每种纸币剩余张数
坑点来了!纸币的转换不一定只是转换成单一种类,比如说100=50+10*2+5*4+1*10
那么这个就很麻烦了…我的处理方法如下,假设数组从1-5分别代表100、50、10、5、1。假设我们想转换的面值位置为i,那么
1.先尝试换i之后位置面值的某一种,比如100=50*2=10*10=5*20=1*100
2.用贪心将i位置面值,转换成i之后面值的组合。如果能转换,则转换,不能拉到。我们考虑极限情况,可能出现剩下50*1、10*9、5*19、1*99,也就是说当前i可以再转换的次数不一定只有1次,没关系,我们while循环多搞几次即可!
实现比较复杂,我的代码也比较难看,尽量用注释说明
#include<bits/stdc++.h> using namespace std; long long p,a1,a5,a10,a50,a100; long long has[6]; //代表某面值纸币有多少张 long long value[6]={0}; //最大最小张数计算中每种面值使用的张数 int price[6]={0,100,50,10,5,1}; //纸币的面额 long long maxx,minn; int main(){ int t; scanf("%d",&t); while(t--){ //scanf("%lld%lld%lld%lld%lld%lld",&p,&a1,&a5,&a10,&a50,&a100); scanf("%lld%lld%lld%lld%lld%lld",&p,&has[5],&has[4],&has[3],&has[2],&has[1]); long long temp=p; //先找到用张数最少的情况 value[1]=temp/100; if(value[1]>has[1]){ //注意每次求的时候考虑面额最多张数 value[1]=has[1]; temp-=100*has[1]; } else { temp%=100; } value[2]=temp/50; if(value[2]>has[2]){ value[2]=has[2]; temp-=50*has[2]; } else { temp%=50; } value[3]=temp/10; if(value[3]>has[3]){ value[3]=has[3]; temp-=10*has[3]; } else { temp%=10; } value[4]=temp/5; if(value[4]>has[4]){ value[4]=has[4]; temp-=5*has[4]; } else { temp%=5; } value[5]=temp; if(value[5]>has[5]){ value[5]=has[5]; temp-=1*has[5]; } else { temp%=1; } if(temp==0){ //如果我们 temp用光了,说明可以正好转换 minn=value[1]+value[2]+value[3]+value[4]+value[5]; } else { cout<<-1<<" "<<-1<<endl; continue; } //cout<<value[1]<<" "<<value[2]<<" "<<value[3]<<" "<<value[4]<<" "<<value[5]<<endl; long long temp1,temp2; for(int i=1;i<5;i++){ for(int j=i+1;j<=5;j++){ //和i以后的每一个面额的转换 temp1=has[j]-value[j]; //i位置面额可以转换多少张 temp2=temp1/(price[i]/price[j]); //转换成j位置面额可以有多少张 if(value[i]>temp2){ value[i]-=temp2; value[j]+=temp2*(price[i]/price[j]); } else{ value[j]+=value[i]* (price[i]/price[j]); value[i]=0; } } int ttt=10; //多循环几次找出i位置转换成不同面额组合的不同情况 if(value[i]>0){ while(ttt--&&value[i]>0){ //当使用的i面额没有了跳出 int use[6]={0}; //记录转换使用的张数,如果转换成功了,需要用use和value更新 int target=price[i]; //转换的目标值 long long temp4; for(int k=i+1;k<=5;k++){ temp4=target/price[k]; //剩余值可以转换成k的张数 if(temp4>has[k]-value[k]){ target-=(has[k]-value[k])*price[k]; use[k]=has[k]-value[k]; } else { use[k]+=temp4; target-=temp4*price[k]; } if(target==0){ //如果转换成功 value[i]--; for(int kk=1;kk<=5;kk++){ //更新状态值 value[kk]+=use[kk]; } break; } } } } //cout<<value[1]<<" "<<value[2]<<" "<<value[3]<<" "<<value[4]<<" "<<value[5]<<endl; } maxx=value[1]+value[2]+value[3]+value[4]+value[5]; cout<<minn<<" "<<maxx<<endl; } return 0; }
相关文章推荐
- HDU 3969 Crazy Basketball Fan 模拟
- HDU 1387(模拟优化)
- hdu 36832010 Asia Hangzhou Regional Contest Gomoku 模拟、枚举
- HDU 3644 计算几何 模拟退火
- 【模拟】HDU 4134
- hdu 3688 蛮巧的模拟
- 【模拟】2011 Asia ChenDu Regional Contest 成都现场赛 hdu 4119
- 【模拟】2011 Asia Fuzhou Regional Contest hdu 4121
- HDU 1042 N!(模拟)
- HDU 3004 the chess 【bfs模拟】
- hdu 1020 Encoding(模拟)
- hdu 3348
- HDU 1042 N! (模拟 高精度)
- hdu 1303 Doubles(模拟)
- hdu Single CPU, multi-tasking 模拟cpu题
- HDU 3348 coins 贪心
- 【几何模拟】hdu 3286
- HDU 4068 模拟
- 模拟 hdu 1103 Flo's Restaurant
- hdu 1035很简单的一个模拟