2019 Multi-University Training Contest 9 Rikka with Coin(思维)

题意:
Rikka手中有无数个面值为10美分,20美分,50美分,1美元的硬币,现在有n件商品,每件商品的价格为ai元,问Rikka最少需要携带多少个硬币,使得买每一件商品都不用找零(商品与商品之间互不影响)。如果一定得找零则输出-1。

题解:
如果某件商品的价格膜10不为0,则一定得找零,输出-1.
然后,10美分的硬币最多只会用1个,如果需要2颗10美分的硬币,选取1颗10美分和1颗20美分的硬币会更优。
然后,20美分的硬币最多只会用3个,如果需要4颗20美分的硬币,选取1颗10美分,2颗20美分,1颗50美分的硬币会更优。
然后,50美分的硬币最多只会用1个,如果需要2个50美分的硬币,选取1颗50美分和1颗1美元的硬币会更优。
剩下的用1美元的补充即可。

所以最多拿1颗10美分,3颗20美分,1颗50美分,总共有16种情况,用一个四位数组记录取i个10,j个20,k个50的和,而且和最大为120.
对于所有情况,我们先判断这个值是否大于100,如果大于100,则判断这个值a % 100 + 100(因为10,20,50最大和才100,因此加100)后能不能由前面的10,20,50构成,如果可以,则需要1美元的个数为a / 100 - 1,如果不能,那么需要1美元的个数为a / 100;如果这个值小于100,那么只需判断这个数能否由i个10,j个20,k个50组成即可,最终维护最小值minn。

AC_Code:

#include <bits/stdc++.h>
using namespace std;

#define inf 0x3f3f3f3f
bool s[2][4][2][200];// 最多1个10,3个20,1个50,和为120
int a[123];

void init(){
	memset(s,false,sizeof(s));
	for(int i=0; i<2; ++i)
		for(int j=0; j<4; ++j)
			for(int k=0; k<2; ++k)
				for(int l=0; l<=i; ++l)
					for(int m=0; m<=j; ++m)
						for(int n=0; n<=k; ++n)
							s[i][j][k][10*l+m*20+n*50] = true;
} 

int main(){
	freopen("in.txt","r",stdin);
	init();
	int t;
	while(~scanf("%d",&t)){
		while(t--){
			int n;bool flag = false;
			scanf("%d",&n);
			for(int i=0; i<n; ++i){
				scanf("%d",&a[i]);
				if(a[i] % 10){
					flag = true;
				}
			}
			if(flag){
				puts("-1");
				continue;
			}
			int minn = inf;
			for(int i=0; i<2; ++i){
				for(int j=0; j<4; ++j){
					for(int k=0; k<2; ++k){
						int sum = 0, ans = 0;
						for(int l=0; l<n; ++l){
							if(a[l] >= 100 && s[i][j][k][a[l]%100+100]){ // 110 120 210 220 310 320
								ans = a[l] / 100 - 1;
							}
							else if(s[i][j][k][a[l] % 100]){
								ans = a[l] / 100;
							}
							else{
								ans = inf;
							}
							sum = max(sum,ans);
						}
						minn = min(minn, sum + i + j + k);
					}
				}
			}
			cout << minn << endl;
		}
	}
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值