3306. 有钱人买钻石
单点时限: 2.0 sec
内存限制: 256 MB
有一个有钱人,他身上带了好多硬币。但是这么多硬币由不方便带,所以他决定要用这些硬币去买钻石。
有趣的是,店里只剩下一颗钻石了。这颗钻石的价格是 P。他身边由一元硬币 N1 枚,五元硬币 N2 枚,十元硬币 N3 枚,二十五元硬币 N4 枚。这些硬币都是一样重的。有钱人当然希望花的硬币越重越好,也就是说数量越多越好,但也不想让商家找钱。你知道应该怎么做吗?
输入格式
第一行一个整数 P,第二行用空格隔开的四个整数 N1,N2,N3,N4。(1≤P≤108,0≤N1,N2,N3,N4≤108)。
对于 30% 的数据,有 P≤103,0≤N1,N2,N3,N4≤100。
输出格式
如果办不到,输出 Impossible
,否则输出最多能花掉多少枚硬币。
样例
input
13
3 2 1 1
output
5
input
13
1 1 1 1
output
Impossible
心得: 第一眼看到题目以为是动态规划的背包问题,手贱搜了下题目,看了眼标签greedy,dfs
,就没往dp想了,按照常规思路维护每个票面能否找零。
#include<iostream>
#include<cmath>
#include<vector>
using namespace std;
int aim,money[4]={1,5,10,25},nums[4],useNum[4]={0,0,0,0},ans=0;
int dfs(int x,int ans){
for(int j=0;j<useNum[x];j++){
int creatWeight=0,aimweight=money[x];
vector<int> tmpWeight(4,0);
for(int i=x-1;i>=0;i--){
tmpWeight[i]=min(aimweight/money[i],nums[i]);
creatWeight+=tmpWeight[i];
nums[i]-=tmpWeight[i];
aimweight-=money[i]*tmpWeight[i];
}
if(aimweight!=0){
for(int k=0;k<4;k++)nums[k]+=tmpWeight[k];
break;
}else{
for(int k=0;k<4;k++){
useNum[k]+=tmpWeight[k];
}
ans+=creatWeight-1;
}
}
if(x>1)ans = max(dfs(x-1,ans),ans);
return ans;
}
int main(){
scanf("%d",&aim);
for(int i=0;i<4;i++){
scanf("%d",&nums[i]);
}
int tmpaim=aim;
for(int i=3;i>=0;i--){
useNum[i]=min(tmpaim/money[i],nums[i]);
nums[i]-=useNum[i];
ans+=useNum[i];
tmpaim-=useNum[i]*money[i];
}
if(tmpaim!=0){
cout<<"Impossible"<<endl;
return 0;
}
ans = dfs(3,ans);
cout<<ans<<endl;
}