using namespace std;

map<string, int> ans; // 用map存储每个人的净收入(正数表示收到钱,负数表示支出钱)

int main() {
    // 文件输入输出(适用于竞赛环境)
    freopen("gift.in", "r", stdin);
    freopen("gift.out", "w", stdout);
    
    int n, money; // n:总人数,money:送礼人准备的钱
    cin >> n; // 输入总人数
    
    string name[15]; // 存储所有人的名字(最多15人)
    string s, p; // s:送礼人名字,p:收礼人名字
    
    // 读入所有人的名字
    for (int i = 1; i <= n; i++) {
        cin >> name[i];
    }
    
    // 处理每个人的送礼事件
    for (int i = 1, num; i <= n; i++) {
        cin >> s; // 送礼人名字
        cin >> money; // 送礼人准备的总金额
        cin >> num; // 送礼人数
        
        // 给每个收礼人分配钱
        for (int j = 1; j <= num; j++) {
            cin >> p; // 收礼人名字
            // 每个收礼人获得money/num(整数除法)
            ans[p] += money / num;
        }
        
        // 处理送礼人自己的收支
        if (num != 0) {
            /* 送礼人支出变化:
             * -money:因为拿出了这么多钱
             * +money%num:因为分完剩下的钱又还给了自己
             * 实际效果相当于:支出(money - money%num)
             */
            ans[s] = ans[s] - money + money % num;
        }
    }
    
    // 按输入顺序输出每个人的净收入
    for (int i = 1; i <= n; i++) {
        cout << name[i] << ' ' << ans[name[i]] << endl;
    }
    
    return 0;
}

题目理解 同学们在互送礼物,规则是:

每个同学可以准备一些钱作为礼物

把钱平均分给几个朋友(不能整除时,剩下的钱自己保留)

每个同学也会收到其他朋友送的钱

需要计算每个人最后是"赚钱"了还是"花钱"了

解题思路 记录每个人的收支情况

用map(名字到数字的映射)记录每个人的净收入

正数表示收到的钱比送出的多(赚钱)

负数表示送出的钱比收到的多(花钱)

处理送礼事件

分钱给朋友:把送礼人的钱平均分给朋友们

例如:小明有100元,分给4个朋友,每人100÷4=25元

每个朋友在记录中增加25元

处理余数:分不完的钱还给送礼人

例如:103元分给4个朋友,每人25元(100÷4),剩下3元还给小明

小明的记录:-103(拿出钱)+3(收回余数)= -100元(实际支出)

特殊情况的处理

如果送礼人数为0(没有朋友),就不进行分钱操作

送礼人不会给自己分钱

0 条评论

目前还没有评论...