Rikka with Coin (思维)

Rikka with Coin

Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 524288/524288 K (Java/Others)
Total Submission(s): 580 Accepted Submission(s): 144

Problem Description

Rikka hates coins, and she used to never carry any coins with her. These days, Rikka is doing her summer internship abroad. Without mobile payment, Rikka has to face strange prices of commodities, and as a result of always using paper currency, she has to face mountainous coins on here table.

In the local currency system, there are 4 kinds of coins: 10 cents, 20 cents, 50 cents and 1 dollar. Up to now, Rikka has gained at least 10100 coins for each kind.

Now, Rikka is going to have dinner in the canteen, and she decides to pay the bill only with coins. There are n different combos in the canteen and the price of the ith is wi cents. Rikka would like to choose one combo as dinner but she has not decided to choose which one yet. Therefore, she wants to take some coins so that whichever she chooses, she can always pay the bill without receiving any change.

Since Rikka hates coins, she wants to carry as few coins as possible with her. As it is generally known that Rikka is not good at math, she wants you to help her make the decision.

Input
The first line of the input contains a single integer T(1≤T≤500), the number of test cases.

For each test case, the first line contains a single integer n(1≤n≤100), the number of combos sold in the canteen.

The second line contains n positive integers w1,…,wn(1≤wi≤109), which represents the prices.

Output
For each test case, output a single line with a single integer which represents the minimum number of coins. If there is no valid solution, output −1.

Hint
In the first test case, one optimal solution is to bring one coin of 10 cents and two coins of 20 cents.

In the second test case, one optimal solution is to bring 5 coins of one dollar.

Sample Input

3
5
10 20 30 40 50
5
100 200 300 400 500
1
1

Sample Output

3
5
-1

Solution

 好艰难啊这题。。。。。。。。

开始想到超过100的应该都是直接堆100。于是将所有数据模100,发现只需要10,20,20,50
暴力枚举

但是这种策略是不完全正确的。。110的情况比较特殊,110可以用20,20,20,50 组成,所以必须特判

做了一下午都没发现 20+20+20+50可以凑出110

由于这个样例的特殊性,导致一直没ac

到了晚上,即使知道了这个情况,改起代码来也是相当累相当恐怖。。。
真的改了好久。。。。

AC Code


/*
 * Copyright (c) 2019 Ng Kimbing, HNU, All rights reserved. May not be used, modified, or copied without permission.
 * @Author: Ng Kimbing, HNU.
 * @LastModified:2019-08-12 T 12:09:46.922 +08:00
 */
#include <bits/stdc++.h>

using namespace std;

int w[200];
int n;
set<int> nums;

bool test(int n50, int n20, int n10) {
    for (auto foo:nums) {
        bool flag = false;
        switch (foo) {
            case 10:
            case 11:
                if (n10 < 1)
                    return false;
                break;
            case 20:
                if (n20 < 1)
                    return false;
                break;
            case 30:
                if (n10 < 1 || n20 < 1)
                    return false;
                break;
            case 40:
                if (n20 < 2)
                    return false;
                break;
            case 50:
                if (n10 > 0 && n20 >= 2)
                    flag = true;
                if (n50 > 0)
                    flag = true;
                if (!flag) return false;
                break;
            case 60:
                if (n10 > 0 && n50 > 0)
                    flag = true;
                if (n20 >= 3)
                    flag = true;
                if (!flag) return false;
                break;
            case 70:
                if (n20 > 0 && n50 > 0)
                    flag = true;
                if (n10 > 0 && n20 >= 3)
                    flag = true;
                if (!flag) return false;
                break;
            case 80:
                if (n10 > 0 && n20 > 0 && n50 > 0)
                    flag = true;
                if (n20 >= 4)
                    flag = true;
                if (!flag) return false;
                break;
            case 90:
                if (n50 > 0 && n20 >= 2)
                    flag = true;
                if (!flag) return false;
                break;
        }
    }
    return true;
}

int n50, n20, n10;

void doCase() {
    nums.clear();
    cin >> n;
    int base = 0;
    int mx = 0;
    for (int i = 0; i < n; ++i) {
        cin >> w[i];
        mx = max(mx, w[i]);
    }
    for (int i = 0; i < n; ++i) {
        base = max(base, w[i] / 100);
        nums.insert(w[i] % 100 == 10 && w[i] > 100 ? 11 : w[i] % 100);
        if (w[i] % 10) {
            cout << "-1\n";
            return;
        }
    }
    int ans = 4;
    for (int i = 0; i < 3; ++i)
        for (int j = 0; j < 5; ++j)
            for (int k = 0; i + j + k <= ans; ++k)
                if (i + j + k <= ans && test(i, j, k)) {
                    n50 = i, n20 = j, n10 = k;
                    ans = min(ans, i + j + k);
                }
    if (ans == 4 && nums.count(11) && mx % 100 == 10 && mx > 100 && nums.erase(11) && test(1, 3, 0)) {
        ans = min(ans, 4);
        n20 = 3, n50 = 1, n10 = 0;
        --base;
    }
    if (n10 == 1 && n20 == 2 && n50 == 1 && mx % 100 == 0)
        --base;
    cout << ans + base << endl;
}

//#define BINGOJ_TEST
#ifdef BINGOJ_TEST

#include "BingOj.h"

#endif

int main() {
#ifdef BINGOJ_TEST
    FILE *pIobuf = freopen("1001.in", "r", stdin);
    FILE *pIobuf1 = freopen("myOutput", "w", stdout);
    BingOJ::set_properties("myOutput", "standard1001.out", 1000);
#endif

    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int t;
    cin >> t;
    while (t--)
        doCase();
    cout << flush;

#ifdef BINGOJ_TEST
    fclose(pIobuf);
    fclose(pIobuf1);
    BingOJ::normal_judge();
#endif
    return 0;
}


/*
65465564
5
10 20 40 50 110
4
50 70 90 120

6
10 20 30 40 50 500
*/

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值