zoukankan      html  css  js  c++  java
  • UVa OJ 119 Greedy Gift Givers (贪婪的送礼者)

    Time limit: 3.000 seconds
    限时:3.000秒

    The Problem
    问题

    This problem involves determining, for a group of gift-giving friends, how much more each person gives than they receive (and vice versa for those that view gift-giving with cynicism).
    这问题是要来确定一组相互送礼的朋友中,有多少付出大于回报的人(或与之相对的那些只进不出的白眼狼)。

    In this problem each person sets aside some money for gift-giving and divides this money evenly among all those to whom gifts are given.
    问题中每个朋友都拿出一笔钱用来送礼,并将这笔钱平均分配给他所有的朋友。

    However, in any group of friends, some people are more giving than others (or at least may have more acquaintances) and some people have more money than others.
    然而无论在哪个朋友圈子中,总会有某些人给的比别人多(或着是比别人的熟人多),而有些人的钱比较多。

    Given a group of friends, the money each person in the group spends on gifts, and a (sub)list of friends to whom each person gives gifts; you are to write a program that determines how much more (or less) each person in the group gives than they receive.
    给定一个朋友圈、以及其中每个人在购买礼物上所花的钱,还有每个人将要送礼的朋友列表;你来写一个程序计算在这个朋友圈中有多少人的付出大于回报。

    The Input
    输入

    The input is a sequence of gift-giving groups. A group consists of several lines:
    输入是一组相互送礼的朋友圈。一个圈子由下面数行构成:

    • the number of people in the group,
      圈子中的人数,
    • a list of the names of each person in the group,
      圈子中每个人的姓名,
    • a line for each person in the group consisting of the name of the person, the amount of money spent on gifts, the number of people to whom gifts are given, and the names of those to whom gifts are given.
      每个人独占一行,包括姓名、用于购礼的总金额、要送礼的人数以及每个要送的人的名字。

    All names are lower-case letters, there are no more than 10 people in a group, and no name is more than 12 characters in length. Money is a non-negative integer less than 2000.
    所有名字都是小字字母,每个圈子不会超过10个人,所有名字都小于或等于12个字符长度。总金额为小于2000的非负整数。

    The input consists of one or more groups and is terminated by end-of-file.
    在输入一个圈子或多个圈子后,由EOF表示结束。

    The Output
    输出

    For each group of gift-givers, the name of each person in the group should be printed on a line followed by the net gain (or loss) received (or spent) by the person. Names in a group should be printed in the same order in which they first appear in the input.
    对于每组相互送礼的朋友圈,其中的每个人都要输出一行:前面是姓名,后面是他的净收入(可能为负,表示他的付出大于回报)。圈子中的姓名要按照输入的第二行中给出的顺序输入。

    The output for each group should be separated from other groups by a blank line. All gifts are integers. Each person gives the same integer amount of money to each friend to whom any money is given, and gives as much as possible. Any money not given is kept and is part of a person's "net worth" printed in the output.
    每个圈子的输出要与其它圈子的输出相隔一个空行。所有礼物价值都为整数。对每个人而言,赠给各位朋友的礼金总数都相同,并会尽可能多的赠出。没有给出的零头要加入到他的净收入中一并输出。

    Sample Input
    输入示例

    5
    dave laura owen vick amr
    dave 200 3 laura owen vick
    owen 500 1 dave
    amr 150 2 vick owen
    laura 0 2 amr vick
    vick 0 0
    3
    liz steve dave
    liz 30 1 steve
    steve 55 2 liz dave
    dave 0 2 steve liz

    Sample Output
    输出示例

    dave 302
    laura 66
    owen -359
    vick 141
    amr -150

    liz -3
    steve -24
    dave 27

    Analysis
    分析

    这道题是纯语言题,可以拿来练习使用STL,看最少多少行能解决问题(下面给出的代码有效行数为29行)。没有算法,也没什么好分析的。唯一要注意的是:第一个圈子的结果输出时上下都不能有空行,后面所有的圈子上面要有一个空行(在输入的数据之后)。位置绝对不能错,否则WA。

    Solution
    解答

    #include <algorithm>
    #include <iostream>
    #include <iterator>
    #include <string>
    #include <vector>
    using namespace std;
    //主函数
    int main(void) {
    	//循环处理输入的每组朋友圈
    	for (int nPeople, nFirst = 1; cin >> nPeople; nFirst = 0) {
    		//vecName按顺序存储各人姓名,vecWorth为各人净收入
    		vector<string> vecName(nPeople);
    		vector<int> vecWorth(nPeople, 0);
    		//输入所有人的姓名
    		for (int i = 0; i < nPeople; cin >> vecName[i++]);
    		//循环处理每个人的收支
    		for (int i = 0, nMoney, nFriCnt; i < nPeople; ++i) {
    			//读入姓名,金额和朋友数
    			string strName;
    			cin >> strName >> nMoney >> nFriCnt;
    			//找到此人在数组中的位置
    			vector<string>::iterator iPeople = find(
    				vecName.begin(), vecName.end(), strName);
    			int &nCurWorth = vecWorth[distance(vecName.begin(), iPeople)];
    			//从此人净收入中支出金额分平均分给朋友
    			nCurWorth -= nMoney;
    			if (nFriCnt > 0) {
    				//平分到每个朋友的净收入中
    				for (int j = 0, nShare = nMoney / nFriCnt; j < nFriCnt; ++j) {
    					//找到朋友在数组中的位置,并加入到净收入中
    					cin >> strName;
    					iPeople = find(vecName.begin(), vecName.end(), strName);
    					vecWorth[distance(vecName.begin(), iPeople)] += nShare;
    				}
    				//计算平分后剩下的零头
    				nMoney %= nFriCnt;
    			}
    			//如果剩有零头或未分给任何朋友,则返回净收入
    			nCurWorth += nMoney;
    		}
    		//按照要求,每组输出间要以空行隔开,但第一组前面不能有空行
    		cout << (nFirst == 1 ? "" : "\n");
    		//按顺序输出结果,每行前面是姓名,后面是净收入,用空格隔开
    		for (int i = 0; i != vecName.size(); ++i) {
    			cout << vecName[i] << ' ' << vecWorth[i] << endl;
    		}
    	}
    	return 0;
    }
    



    知识共享许可协议 作者:王雨濛;新浪微博:@吉祥村码农;来源:《程序控》博客 -- http://www.cnblogs.com/devymex/
    此文章版权归作者所有(有特别声明的除外),转载必须注明作者及来源。您不能用于商业目的也不能修改原文内容。
  • 相关阅读:
    生成PDF文档
    2016 百度研发岗面试总结
    有趣的数
    2016阿里校招python研发面试
    python 快排,堆排,归并
    三种简单的排序写下贴上
    BestCoder Round #47 1003
    c++ 适配器
    微信公众平台-超级大赛问题汇总1
    正则表达式简单总结
  • 原文地址:https://www.cnblogs.com/devymex/p/1799697.html
Copyright © 2011-2022 走看看