二叉搜索树+贪心—Find Coins

本文介绍了一种使用二叉搜索树和贪心策略解决特定硬币组合查找问题的算法。该算法旨在从大量硬币中寻找两个硬币,其面值之和等于给定的目标值。若存在多个解,则输出硬币面值最小的组合。文章详细阐述了算法的实现过程,包括数据结构的选择、插入和查找操作,并提供了完整的代码示例。

1048 Find Coins (25分)

题目大意:你有n(最多105)这么多的硬币,找出2个硬币满足m,有多个解决方案,输出其中一个硬币面值最小的组合,找不出则输出No Solution

输入样例1

8 15
1 2 8 7 2 4 11 15

输出样例1

4 11

输入样例2

7 14
1 8 7 2 4 11 15

输出样例2

No Solution

我使用的方法是用二叉搜索树存储数据加贪心,从i=1和m-i开始找,找到直接输出,直到i>m/2,找不到就输出No Solution.

代码

#include <iostream>
#include <algorithm>
using namespace std;
typedef struct TreeNode *BST;
struct TreeNode{
    int data;
    BST Left,Right;
    int visited;
};
void Clean(BST T){
    T->visited++;
}
BST Insert(BST T,int x){
    if(!T){
        T=(BST)malloc(sizeof(struct TreeNode));
        T->data=x;
        T->visited++;
        T->Left=T->Right= nullptr;
    } else{
        if(x<T->data)
            T->Left=Insert(T->Left,x);
        else if (x>T->data)
            T->Right=Insert(T->Right,x);
        else
            T->visited++;
    }
    return T;
}
BST Finddata(BST T,int x){
    if(T){
        if(x==T->data){
            if (T->visited>0){
                T->visited--;
                return T;
            } else
                return nullptr;
        }
        else if(x<T->data)
            return Finddata(T->Left,x);
        else if (x>T->data)
            return Finddata(T->Right,x);
    } else
        return T;
}
int main()
{
    int n,m;
    cin>>n>>m;
    int a[n+1];
    int flag=0;
    for (int i = 0; i < n; ++i) {
        cin>>a[i];
    }
    sort(a,a+n);
    int i,j=n/2;
    BST T= nullptr;
    for (i = 0; i <= n/2; ++i) {
        if(i!=n/2)
            T=Insert(T,a[j+i]);
        if(i!=0)
            T=Insert(T,a[j-i]);
    }
    BST temp;
    for(i=1;i<=m/2;i++){
        temp=Finddata(T,i);
        if(temp){
            if(Finddata(T,m-i)){
                cout<<i<<' '<<m-i;
                flag=1;
                break;;
            } else
                Clean(temp);
        }
    }
    if (!flag)
        cout<<"No Solution";
    return 0;
}
c++#include <iostream> #include <algorithm> #include <climits> #include <fstream> using namespace std; const int denominations[] = {200, 100, 50, 20, 10, 5}; int minChange(int amount) { int count = 0; for (int coin : denominations) { if (amount >= coin) { count += amount / coin; amount %= coin; } } return (amount == 0) ? count : INT_MAX; } void dfs(int idx, int remaining, int used, const int counts[], int& min_coins) { if (remaining == 0) { if (used < min_coins) { min_coins = used; } return; } if (idx == 6 || used >= min_coins) { return; } dfs(idx + 1, remaining, used, counts, min_coins); int max_take = min(remaining / denominations[idx], counts[idx]); for (int take = 1; take <= max_take; ++take) { dfs(idx + 1, remaining - take * denominations[idx], used + take, counts, min_coins); } } int minCoinsForPayment(int amount, const int counts[]) { int min_coins = INT_MAX; dfs(0, amount, 0, counts, min_coins); return min_coins; } int main() { ifstream infile("input.txt"); ofstream outfile("output.txt"); while (true) { int coins[6]; for (int i = 0; i < 6; ++i) { infile >> coins[i]; } if (coins[0] == 0 && coins[1] == 0 && coins[2] == 0 && coins[3] == 0 && coins[4] == 0 && coins[5] == 0) { break; } double payment_double; infile >> payment_double; int payment = static_cast<int>(payment_double * 100 + 0.5); int min_total = INT_MAX; int max_possible_change = 200 * coins[5] + 100 * coins[4] + 50 * coins[3] + 20 * coins[2] + 10 * coins[1] + 5 * coins[0]; int max_enumerate = payment + 2000; for (int P = payment; P <= payment + max_possible_change && P <= max_enumerate; ++P) { int change = P - payment; if (change < 0) continue; int payment_coins = minCoinsForPayment(P, coins); if (payment_coins == INT_MAX) continue; int change_coins = minChange(change); if (change_coins == INT_MAX) continue; if (payment_coins + change_coins < min_total) { min_total = payment_coins + change_coins; } } if (min_total != INT_MAX) { outfile << min_total << endl; } else { outfile << "impossible" << endl; } } infile.close(); outfile.close(); return 0; }
最新发布
10-30
下面是对 C++ 硬币找钱问题代码的优化,实现最少硬币个数交易方案计算并将结果输出到文件。原代码(引用[3])只是计算了每种硬币的使用数量,而这里会着重计算最少硬币个数,并将结果输出到文件。 ```cpp #include <iostream> #include <fstream> using namespace std; int main() { int money, penny, nickel, dime, quarter; // 打开输出文件 ofstream outFile("output.txt"); if (!outFile.is_open()) { cerr << "无法打开输出文件!" << endl; return 1; } while (cin >> money >> penny >> nickel >> dime >> quarter) { int coinCount = 0; int q = money / 25; if (q <= quarter) { money -= q * 25; coinCount += q; } else { q = quarter; money -= q * 25; coinCount += q; } int d = money / 10; if (d <= dime) { money -= d * 10; coinCount += d; } else { d = dime; money -= d * 10; coinCount += d; } int n = money / 5; if (n <= nickel) { money -= n * 5; coinCount += n; } else { n = nickel; money -= n * 5; coinCount += n; } int p = money; if (p <= penny) { coinCount += p; outFile << "最少需要的硬币个数: " << coinCount << endl; } else { outFile << "Not enough change" << endl; } } // 关闭输出文件 outFile.close(); return 0; } ``` ### 代码说明 1. **文件操作**:使用 `ofstream` 打开一个名为 `output.txt` 的文件,用于输出结果。如果文件无法打开,程序会输出错误信息并终止。 2. **最少硬币个数计算**:在计算每种硬币使用数量的同时,累加使用的硬币个数到 `coinCount` 变量中。 3. **结果输出**:根据计算结果,将最少硬币个数或 “Not enough change” 输出到文件中。 4. **文件关闭**:在程序结束前,关闭输出文件。
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值