微软挑战赛之传话游戏问题

来源:互联网 发布:.shop域名价值 编辑:程序博客网 时间:2024/05/18 01:41

时间:2014.01.26

地点:基地二楼

-------------------------------------------------------------------

一、简述

  今天看到了微软编程之美全国挑战赛的题目,于是拿来试试,发现还是很基础的,只要基础牢固,我想写出来的程序应该还是很靠谱的。

-------------------------------------------------------------------

二、题目

描述

AliceBob还有其他几位好朋友在一起玩传话游戏。这个游戏是这样进行的:首先,所有游戏者按顺序站成一排,Alice站第一位,Bob站最后一位。然后,Alice想一句话悄悄告诉第二位游戏者,第二位游戏者又悄悄地告诉第三位,第三位又告诉第四位……以此类推,直到倒数第二位告诉Bob。两位游戏者在传话中,不能让其他人听到,也不能使用肢体动作来解释。最后,Bob把他所听到的话告诉大家,Alice也把她原本所想的话告诉大家。 

由于传话过程中可能出现一些偏差,游戏者越多,Bob最后听到的话就与Alice所想的越不同。Bob听到的话往往会变成一些很搞笑的东西,所以大家玩得乐此不疲。经过几轮游戏后,Alice注意到在两人传话中,有些词汇往往会错误地变成其他特定的词汇。Alice已经收集到了这样的一个词汇转化的列表,她想知道她的话传到Bob时会变成什么样子,请你写个程序来帮助她。

输入

输入包括多组数据。第一行是整数 T,表示有多少组测试数据。每组数据第一行包括两个整数 N  M,分别表示游戏者的数量和单词转化列表长度。随后有 M 行,每行包含两个用空格隔开的单词 a  b,表示单词 a 在传话中一定会变成 b。输入数据保证没有重复的 a。最后一行包含若干个用单个空格隔开的单词,表示Alice所想的句子,句子总长不超过100个字符。所有单词都只包含小写字母,并且长度不超过20,同一个单词的不同时态被认为是不同的单词。你可以假定不在列表中的单词永远不会变化。

输出

对于每组测试数据,单独输出一行“Case #c: s”。其中,为测试数据编号,Bob所听到的句子。的格式与输入数据中Alice所想的句子格式相同。

数据范围

1 ≤ T ≤ 100

小数据:2 ≤ N ≤ 10, 0 ≤ M ≤ 10 

大数据:2 ≤ N ≤ 100, 0 ≤ M ≤ 100 

 

样例输入

2

4 3

ship sheep

sinking thinking

thinking sinking

the ship is sinking

10 5

tidy tiny

tiger liar

tired tire

tire bear

liar bear

a tidy tiger is tired

样例输出

Case #1: the sheep is thinking

Case #2: a tiny bear is bear

-------------------------------------------------------------------

三、分析

  题目虽简单,但涉及的基础知识还是很多的,有很多细节的地方需要注意,比如限制条件,检查输入字符串的合法性等等。下面逐一分析:

3.1 首先,我们要检查数据范围的合法性,我们将代表人数的参数N和代表转换列表行数的M放在一起检查,代码如下:

bool IsParameterLeagal(char n, char m){//Postcondition: check the parameter's leagal and return the resultbool is_n_m_leagal = ((n <= 10 && n >= 2) && (m <= 10 && m >= 0))|| ((n <= 100 && n >= 2) && (m <= 100 && m >= 0));return is_n_m_leagal;}
为什么要返回一个bool值呢,我是想到时还结合别的数据检验一起做个断言,而这里只是对输入合法性检测的一部分,所以这里检测后返回一个bool值,只表示对这两个参数的合法性做出判断。

3.2  其次,要求中有对输入语句的要求,所以这里也要检查:

bool IsInputStringLeagal(const string& input_str){//Postcondition: check the input sttring's leagal and return the result//Library facilities used: sstreamif (input_str.length() >100)return false;istringstream record(input_str);string word;while (record >> word){if (word.length() > 20)return false;for (auto c : word)if (!islower(c))return false;}return true;}
这里可用到一些短路求值方式,即一旦发现不合法了,及时返回为false
3.3   这里是输入数据处理部分,包括基本信息,比如多少个测试样例。N表示参与传话的人数,涉及N-1次传话,所以要在一个N-1次循环中不断变化。

string InputDataProcess(){//Postcondtion: Input information and data process//Library facilities used: assert,mapunsigned N, M;cin >> N >> M;assert(IsParameterLeagal(N, M));map<string, string> transfer_map;while (M != 0){string origin_word, transfer_word="";cin >> origin_word >> transfer_word;transfer_map.insert({ origin_word, transfer_word });M--;}string transfer_words;getchar();getline(cin, transfer_words);assert(IsInputStringLeagal(transfer_words));while (N != 1){transfer_words = TransferWords(transfer_words, transfer_map);N--;}return transfer_words;}
这里要说道的是转换列表的构建,我用了一个map容器,主要是为了后面的方便查找,提高效率。还一个需要注意的地方时getchar()的使用,这里是要吃掉回车,刚开始时在这地方纠结了好久,因为getline()函数一直读不进我想要的一行字符串,而是一个空字符串,而我单独测试getline函数的用法时又没有问题,好蹊跷,后来才晓得cin字符串的,它会将换行符依然放置在流中,所以getline紧接着还是读到换行符,而它一触碰到换行符就结束,所以得到的是一个空字符串,用getchar吃掉这个换行符就OK了。这段代码我觉得还可以优化下,使得代码看起来结构更简洁优雅,比如建立转化表的部分完全可独立出来成为一个模块,可读性就更高了。

3.4下面部分是字符串转换函数,模拟两个人之间的通话,在这个过程中有些词汇会按照转换列表指定的格式做相应的转换,我们用到了sstringstream流对象,将字符串与一个istringstream对象绑定,逐个查询每个单词,该转换的转换,不该转换的保留。

string TransferWords(const string& input_str,const map<string,string>& given_map){//Postcontion: When a communicate occured between two persons,the words will transfer //             according the transfer list. istringstream record(input_str);string word, transfer_words="";while (record >> word){auto it = given_map.find(word);if (it != given_map.end())transfer_words += (" "+it->second);elsetransfer_words += (" " + word);}return transfer_words;}

3.5  一下是主函数部分,在这一节中可以体现程序的整体结构,程序分别对每组测试进行处理,之后将结果存储在一个向量之后,最后再去变量向量容器,把结果按要求打印出来。

int main(){unsigned T;cin >> T;assert(T <= 100 && T >= 0);vector<string> transfer_vec;while (T!=0){string out_string =InputDataProcess();transfer_vec.push_back(out_string);T--;}unsigned count = 1;for (auto str : transfer_vec){cout << "Cade #" << count << ":" << str << endl;count++;}return 0;}
-------------------------------------------------------------------

四、完整代码

#include<iostream>#include<string>#include<cassert>#include<vector>#include<map>#include<sstream>#include<cctype>using namespace std;bool IsParameterLeagal(char n, char m){//Postcondition: check the parameter's leagal and return the resultbool is_n_m_leagal = ((n <= 10 && n >= 2) && (m <= 10 && m >= 0))|| ((n <= 100 && n >= 2) && (m <= 100 && m >= 0));return is_n_m_leagal;}bool IsInputStringLeagal(const string& input_str){//Postcondition: check the input sttring's leagal and return the result//Library facilities used: sstreamif (input_str.length() >100)return false;istringstream record(input_str);string word;while (record >> word){if (word.length() > 20)return false;for (auto c : word)if (!islower(c))return false;}return true;}string TransferWords(const string& input_str,const map<string,string>& given_map){//Postcontion: When a communicate occured between two persons,the words will transfer //             according the transfer list. istringstream record(input_str);string word, transfer_words="";while (record >> word){auto it = given_map.find(word);if (it != given_map.end())transfer_words += (" "+it->second);elsetransfer_words += (" " + word);}return transfer_words;}string InputDataProcess(){//Postcondtion: Input information and data process//Library facilities used: assert,mapunsigned N, M;cin >> N >> M;assert(IsParameterLeagal(N, M));map<string, string> transfer_map;while (M != 0){string origin_word, transfer_word="";cin >> origin_word >> transfer_word;transfer_map.insert({ origin_word, transfer_word });M--;}string transfer_words;getchar();getline(cin, transfer_words);assert(IsInputStringLeagal(transfer_words));while (N != 1){transfer_words = TransferWords(transfer_words, transfer_map);N--;}return transfer_words;}int main(){unsigned T;cin >> T;assert(T <= 100 && T >= 0);vector<string> transfer_vec;while (T!=0){string out_string =InputDataProcess();transfer_vec.push_back(out_string);T--;}unsigned count = 1;for (auto str : transfer_vec){cout << "Cade #" << count << ":" << str << endl;count++;}return 0;}



0 0
原创粉丝点击