2019杭电多校 第九场 6685-Rikka with Coin【思维+暴力】
题目:
http://acm.hdu.edu.cn/showproblem.php?pid=6685
参考资料:
https://blog.csdn.net/qq_41360176/article/details/99762515
大致题意:
餐厅中有n种不同价格的菜品,你有非常非常多的10美分,20美分,50美分,100美分(1美元)的硬币,问你要最少带多少个硬币能在餐厅中吃任意的菜品且不会被找零。
思路:
一开始我以为是背包,然而大错特错,赛后看题解内心复杂,其实是一道思维+暴力题,分析后会发现
10美分硬币最多拿1个,因为拿2个的话不如拿1*10美分+1*20美分
。
同理20美分最多拿3个,拿4个的话不如拿1*10美分+2*20美分+1*50美分
50美分最多拿1个,拿2个的话不如拿1*50美分+1*100美分
不过有个两个特例:
有特殊的数据:110 40 60 50 答案是 50+20+20+20 不用拿一百的
还有一种 :10 90 100 答案是 50+20+20+10 也不用拿一百的
如果这个数字是100的倍数,并且当前10 20 50 的硬币可以凑成100,则计算100的硬币少拿一个,110也是类似的判断。
代码:
#include<iostream>
#include<string.h>
#include<algorithm>
using namespace std;
#define INF 0x3f3f3f3f
int judge(int i10, int i20, int i50, int num) {
for(int i = 0; i <= i10; i++)
for(int j = 0; j <= i20; j++)
for(int k = 0; k <= i50; k++)
if(i*10+j*20+k*50 == num)
return 1;
return 0;
}
int main() {
int t;
scanf("%d",&t);
while(t--) {
int n, flag = 0;
int a[1000];
memset(a,0,sizeof(a));
scanf("%d",&n);
for(int i = 1; i <= n; i++) {
scanf("%d",&a[i]);
if(a[i] % 10 != 0)
flag = 1;
}
if(flag == 1) {
printf("-1\n");
continue;
}
int min_ans = INF;
for(int i = 0; i <= 1; i++) { //10
for(int j = 0; j <= 3; j++) { //20
for(int k = 0; k <= 1; k++) { //50
int ans = -1;
int cnt = 0;
for(int r = 1; r <= n; r++) {
int count = a[r] / 100;
if((a[r]>=100) && (a[r]%100==0) && (judge(i,j,k,100)==1))
count--;//判断情况100
else if((a[r]>100) && (a[r]%100==10) && (judge(i,j,k,110)==1))
count--;//判断情况110
else if(judge(i,j,k,(a[r] % 100)) == 0)
break;
ans = max(ans,(count+i+j+k));
cnt = r;
}
if(cnt == n)
min_ans = min(min_ans, ans);
}
}
}
printf("%d\n",min_ans);
}
return 0;
}