1 条题解

  • 0
    @ 2025-5-22 20:11:29

    解决思路

    1. 计算净支付:对于每个人,计算所有交易后的净支付。即,对于每个人,净支付 = 他支付给别人的总金额 - 别人支付给他的总金额。
    2. 分类处理:将所有人分为两类:净支付为正的人(需要收回钱)和净支付为负的人(需要支付钱)。
    3. 匹配交易:通过一系列的转账,使得所有净支付为正的人的钱被净支付为负的人抵消。具体来说,可以每次选择一个需要收回钱的人和一个需要支付钱的人,进行他们之间的转账,直到所有人的净支付为零。

    实现步骤

    1. 读取输入:读取每个测试用例的旅行者数量和交易数量,然后读取旅行者名字和交易记录。
    2. 计算净支付:初始化一个数组或字典来记录每个人的净支付。对于每笔交易,更新相关两个人的净支付。
    3. 生成平衡交易:将净支付为正和负的人分开,然后通过遍历这些列表生成最终的平衡交易。每次处理一个需要收回钱的人和一个需要支付钱的人,转账金额为两者净支付的较小绝对值。
    4. 输出结果:按照要求的格式输出每个测试用例的结果。

    解决代码

    #include <iostream>
    #include <string>
    #include <vector>
    #include <map>
    using namespace std;
    
    int main() {
        int caseNum = 0;
        int n, t;
        
        while (true) {
            cin >> n >> t;
            if (n == 0 && t == 0) break;
            
            caseNum++;
            cin.ignore(); // 忽略换行符
            
            vector<string> names(n);
            for (int i = 0; i < n; i++) {
                getline(cin, names[i]);
            }
            
            map<string, int> balance;
            for (int i = 0; i < n; i++) {
                balance[names[i]] = 0;
            }
            
            for (int i = 0; i < t; i++) {
                string name1, name2, amountStr;
                getline(cin, name1, ' ');
                getline(cin, name2, ' ');
                getline(cin, amountStr);
                
                int amount = 0;
                for (size_t j = 0; j < amountStr.length(); j++) {
                    amount = amount * 10 + (amountStr[j] - '0');
                }
                
                balance[name1] -= amount;
                balance[name2] += amount;
            }
            
            vector<pair<string, int> > creditors;
            vector<pair<string, int> > debtors;
            
            for (vector<string>::iterator it = names.begin(); it != names.end(); ++it) {
                string name = *it;
                if (balance[name] > 0) {
                    creditors.push_back(make_pair(name, balance[name]));
                } else if (balance[name] < 0) {
                    debtors.push_back(make_pair(name, -balance[name]));
                }
            }
            
            vector<pair<pair<string, string>, int> > transactions;
            int i = 0, j = 0;
            
            while (i < (int)creditors.size() && j < (int)debtors.size()) {
                string creditor = creditors[i].first;
                int credAmount = creditors[i].second;
                string debtor = debtors[j].first;
                int debtAmount = debtors[j].second;
                
                int amount = (credAmount < debtAmount) ? credAmount : debtAmount;
                transactions.push_back(make_pair(make_pair(debtor, creditor), amount));
                
                creditors[i].second -= amount;
                debtors[j].second -= amount;
                
                if (creditors[i].second == 0) i++;
                if (debtors[j].second == 0) j++;
            }
            
            cout << "Case #" << caseNum << endl;
            for (vector<pair<pair<string, string>, int> >::iterator it = transactions.begin(); 
                 it != transactions.end(); ++it) {
                cout << it->first.second << " " << it->first.first << " " << it->second << endl;
            }
            cout << endl;
        }
        
        return 0;
    }
    
    • 1

    信息

    ID
    1258
    时间
    1000ms
    内存
    256MiB
    难度
    10
    标签
    递交数
    7
    已通过
    1
    上传者