刘汝佳白书推介(第01~04章相关UVaOJ题目练习)
Root :: AOAPC I: Beginning Algorithm Contests (Rujia Liu) :: Volume 0. Getting Started
内容包括:题目列表,相关题目的.cpp(题目,分析,代码)
题目难度参考于:http://www.cnblogs.com/devymex/archive/2010/08/26/1808716.html
[难度:3] 10055 - Hashmat the Brave Warrior
[难度:3] 10071 - Back to High School Physics
[难度:5] 10300 - Ecological Premium
[难度:39] 458 - The Decoder
[难度:42] 494 - Kindergarten Counting Game
[难度:34] 414 - Machined Surfaces
[难度:42] 490 - Rotating Sentences
[难度:37] 445 - Marvelous Mazes
[难度:41] 488 - Triangle Wave
[难度:42] 489 - Hangman Judge
[难度:64] 694 - The Collatz Sequence
[难度:38] 457 - Linear Cellular Automata
正文:
[难度:3] 10055 - Hashmat the Brave Warrior
实质上就是判断大小计算差值的题目。
// 10055_HashmatTheBraveWarrior.cpp /** 10055 - Hashmat the Brave Warrior Time limit: 3.000 seconds Problem A Hashmat the brave warrior Input: standard input Output: standard output Hashmat is a brave warrior who with his group of young soldiers moves from one place to another to fight against his opponents. Before fighting he just calculates one thing, the difference between his soldier number and the opponent's soldier number. From this difference he decides whether to fight or not. Hashmat's soldier number is never greater than his opponent. Input The input contains two integer numbers in every line. These two numbers in each line denotes the number of soldiers in Hashmat's army and his opponent's army or vice versa. The input numbers are not greater than 2^32. Input is terminated by End of File. Output For each line of input, print the difference of number of soldiers between Hashmat's army and his opponent's army. Each output should be in seperate line. Sample Input: 10 12 10 14 100 200 Sample Output: 2 4 100 ___________________________________________________________________________________ Shahriar Manzoor 16-12-2000 **/ /** * 题目分析: * 题目描述的大概意思是:勇士依靠士兵的号码来区分敌友,它自己军队的号码总是会小于友兵。 * 输入:一行输入两行整型数据,第一个是友兵,第二个是敌兵,两兵的顺序也可换转(vice versa),整型数据小于等于2^32。 * 输出:对应行输出两数的差值(difference是指差值)。 * * 由题,先要知道,int的取值范围是2^31,题目要求是2^32,我们可以使用long long int 作为数据类型。 * 另外,经测试,竟然EOF!=scanf()的效率比2 == scanf()高出0.004或者0.008(做了两次测试)。 * 简单地说,输入的是两个大小顺序不一定的long long int数据,输出两者之差。 **/ #include <cstdio> using namespace std; int main() { long long int a, b; while(EOF != scanf("%lld%lld", &a, &b)){ // 这里,当我将判断条件改成 2 == scanf()时,时间效率下降了0.08 printf("%lld\n", a > b ? a - b : b - a); } return 0; }
[难度:3] 10071 - Back to High School Physics
简单的计算位移数学题
// 10071_BackToHigh SchoolPhysics.cpp /** 10071 - Back to High School Physics Time limit: 3.000 seconds Problem B Back to High School Physics Input: standard input Output: standard output A particle has initial velocity(速度) and constant acceleration. If its velocity after certain time is v then what will its displacement(位移) be in twice of that time? Input The input will contain two integers in each line. Each line makes one set of input. These two integers denote the value of v (-100 <= v <= 100) and t(0<=t<= 200) ( t means at the time the particle gains that velocity) Output For each line of input print a single integer in one line denoting the displacement in double of that time. (两倍时间的位移) Sample Input 0 0 5 12 Sample Output 0 120 ___________________________________________________________________________________ Shahriar Manzoor **/ /** * 题目分析: * 这题只要读懂题相信就会做了。 * 高中物理位移,时间,初速度,末速度,加速度之间的关系。 * 假如速度在一段时间t后是v,那么,如果将时间改为2t,位移会是多少? * 根据 s = vo*t + (1/2)a*t^2, 先利用v与t求出a, a = (vt - vo) / t,vo = 0,则:a = v/t * 将公式代入且时间变为两倍: s = (1/2)(v/t)* (2t)^2 = 2vt **/ #include <cstdio> using namespace std; int main() { int v, t; while(EOF != scanf("%d%d", &v, &t)){ printf("%d\n", 2*v*t); } return 0; }
[难度:5] 10300 - Ecological Premium
考英文阅读的数学题。
// 10300_EcologicalPremium.cpp /** 10300 - Ecological Premium Time limit: 3.000 seconds Problem A Ecological Premium Input: standard input Output: standard output Time Limit: 1 second Memory Limit: 32 MB German farmers are given a premium depending on the conditions at their farmyard. Imagine the following simplified regulation: you know the size of each farmer's farmyard in square meters and the number of animals living at it. We won't make a difference between different animals, although this is far from reality. Moreover you have information about the degree the farmer uses environment-friendly equipment and practices, expressed in a single integer greater than zero. The amount of money a farmer receives can be calculated from these parameters as follows. First you need the space a single animal occupies at an average. This value (in square meters) is then multiplied by the parameter that stands for the farmer's environment-friendliness, resulting in the premium a farmer is paid per animal he owns. To compute the final premium of a farmer just multiply this premium per animal with the number of animals the farmer owns. Input The first line of input contains a single positive integer n (<20), the number of test cases. Each test case starts with a line containing a single integer f (0<f<20), the number of farmers in the test case. This line is followed by one line per farmer containing three positive integers each: the size of the farmyard in square meters, the number of animals he owns and the integer value that expresses the farmer’s environment-friendliness. Input is terminated by end of file. No integer in the input is greater than 100000 or less than 0. Output For each test case output one line containing a single integer that holds the summed burden for Germany's budget, which will always be a whole number. Do not output any blank lines. Sample Input 3 5 1 1 1 2 2 2 3 3 3 2 3 4 8 9 2 3 9 1 8 6 12 1 8 1 1 3 10 30 40 9 8 5 100 1000 70 Sample Output 38 86 7445 (The Joint Effort Contest, Problem setter: Frank Hutter) **/ /** * 题目分析: * 这题绝对只是考英文的,读懂了题目后你会发觉它是那么的简单。。。 * you know the size of each farmer's farmyard in square meters and the number of animals living at it. * 它说有农场,并且有一定数量的动物住在里面, * First you need the space a single animal occupies at an average. * 首先需要计算单个动物占的空间,即农场大小(平方米)除以该农场上的动物数目。 * This value (in square meters) is then multiplied by the parameter that stands for the farmer's environment-friendliness, * 然后用刚刚的平均值乘以农场的环境参数 * resulting in the premium a farmer is paid per animal he owns. * 知道了一个农民能从每个动物拿到的奖金 * To compute the final premium of a farmer just multiply this premium per animal with the number of animals the farmer owns. * 最后再用这每个动物的奖金乘以动物的数量得到最终的奖金。 * 简单地来说就是,最终奖金 = ((农场大小/动物数量)*环境参数)*动物数量 = 农场大小*动物数量 * 呃~想不到就是这么简单。 * 输入:第一次输入一个n是测试的次数,第二次输入一个农民的个数,然后输入每个农民的那三个参数。 * 输出:直接用那个公式去计算最终奖金,将每个农民的奖金加起来。 **/ #include <cstdio> using namespace std; int main() { int n, f, space, animal, enviroment; scanf("%d", &n); // 需要测试的数据数目 while(n--){ scanf("%d", &f); // 农民数目 int result = 0; while (f--){ scanf("%d%d%d", &space, &animal, &enviroment); result += space * enviroment; } printf("%d\n", result); } return 0; }
[难度:39] 458 - The Decoder
简单的字符转换
// 458_TheDecoder.cpp /** 458 - The Decoder Time limit: 3.000 seconds The Decoder Write a complete program that will correctly decode a set of characters into a valid message. Your program should read a given file of a simple coded set of characters and print the exact message that the characters contain. The code key for this simple coding is a one for one character substitution based upon a single arithmetic manipulation of the printable portion of the ASCII character set. Input and Output For example: with the input file that contains: 1JKJ'pz'{ol'{yhklthyr'vm'{ol'Jvu{yvs'Kh{h'Jvywvyh{pvu5 1PIT'pz'h'{yhklthyr'vm'{ol'Pu{lyuh{pvuhs'I|zpulzz'Thjopul'Jvywvyh{pvu5 1KLJ'pz'{ol'{yhklthyr'vm'{ol'Kpnp{hs'Lx|pwtlu{'Jvywvyh{pvu5 your program should print the message: *CDC is the trademark of the Control Data Corporation. *IBM is a trademark of the International Business Machine Corporation. *DEC is the trademark of the Digital Equipment Corporation. Your program should accept all sets of characters that use the same encoding scheme and should print the actual message of each set of characters. Sample Input 1JKJ'pz'{ol'{yhklthyr'vm'{ol'Jvu{yvs'Kh{h'Jvywvyh{pvu5 1PIT'pz'h'{yhklthyr'vm'{ol'Pu{lyuh{pvuhs'I|zpulzz'Thjopul'Jvywvyh{pvu5 1KLJ'pz'{ol'{yhklthyr'vm'{ol'Kpnp{hs'Lx|pwtlu{'Jvywvyh{pvu5 Sample Output *CDC is the trademark of the Control Data Corporation. *IBM is a trademark of the International Business Machine Corporation. *DEC is the trademark of the Digital Equipment Corporation. **/ /** * 题目分析: * decode a set of characters into a valid message,转译字符串成为有意义的信息。 * 知道这一点,我们就可以直接观察输入输出的字符串的特点了, * 可以看见的是,输入的字符中,每个字符与输出的字符ASCII中都是相差7,输入-7= 输出。 * 所以转译时除空格字符,其它的只要减七处理就可以了。 **/ #include <cstdio> using namespace std; int main() { char c; while(EOF != (c = getchar())){ if ('\n' == c){ putchar(c); } else{ putchar(c - 7); } } return 0; }
[难度:42] 494 - Kindergarten Counting Game
统计句中单词数量,题中有设陷阱,注意标点与单词之间的关系即可。
// 494_KindergartenCountingGame.cpp /** 494 - Kindergarten Counting Game Time limit: 3.000 seconds Kindergarten Counting Game Everybody sit down in a circle. Ok. Listen to me carefully. ``Woooooo, you scwewy wabbit!'' Now, could someone tell me how many words I just said? Input and Output Input to your program will consist of a series of lines, each line containing multiple words (at least one). A ``word'' is defined as a consecutive sequence of letters (upper and/or lower case). Your program should output a word count for each line of input. Each word count should be printed on a separate line. Sample Input Meep Meep! I tot I taw a putty tat. I did! I did! I did taw a putty tat. Shsssssssssh ... I am hunting wabbits. Heh Heh Heh Heh ... Sample Output 2 7 10 9 **/ /** * 题目分析: * 简单来说,这题就是统计一个句子中的单词数量。 * 这其中有隐藏的要思考的情况是:标点位置与单词位置与空格的位置。 * 在最理想状态时: word word word word word (结果是5) * 这时,只需要用cin的方法读取一行多少个字符串就可以了,因为cin可以忽略空格。 * 假如: word word, word wrod. word (结果是5) * 这时,出现了两个标点,不过,这两个标点出现在单词的后面,这个在读取的时候会连带一起读取,所以不受影响。 * 假如: word.word.wrod word word. .word (结果是6) * 因为它输入一行句子的时候,非字母可以放在任意位置,这时,如果也还是按空格读取,就可能统计的数目变少。 * 因此,我们可以观察这第三种假设的情况:可知,逐个字符读取时,当且仅当由字符变为字母时才累计一个单词。 * 也就是说,我们可以初始化一个判断是字母的状态标记为false, * 然后,当它由字母转换为非字母时,状态变换,增加单词数,当它为非字母的时候,直接设为false. * 也可以这样理解,不是字母的,就是分隔符,当分隔符向字母状态转换时,就累计一个单词,再遇到分隔符,状态设false,不累计。 * 需要注意的是,这时的分隔符不一定只是一个非字母,它可以连续多个非字母,不过,按上面的思路的话,也可以解决这种情况。 * 简单来说,只有字母状态标记由false转为true时,为一个单词,其它的情况都不累加单词数目。 **/ #include <cstdio> #include <iostream> #include <sstream> #include <string> #include <cstring> #include <cctype> using namespace std; int main() { string line; string word; int number; while(getline(cin, line)){ number = 0; istringstream strm(line); while(strm >> word){ bool isAlpha = false; // 是否字母的状态标记。 for (int i = 0; i < word.length(); ++i){ if (isalpha(word[i])){ if(false == isAlpha){ // 判断字母状态是否由false转向true isAlpha = !isAlpha; ++number; // 转换状态,累计单词数目 } } else{ isAlpha = false; // 不是字母时直接将状态设为false. } } } printf("%d\n", number); } return 0; } /* // 第二种相同效率的方法。 // 下面的这种方法跟上面方法相差不大,只是将读取单词的那个步骤去掉了,不过即使去掉了这个步骤, // 在UvaOJ上显示的效率还是一样,所以直接采用上面的那种做法也可以了。 #include <cstdio> #include <iostream> #include <string> #include <cstring> #include <cctype> using namespace std; int main() { string line; int number; while(getline(cin, line)){ number = 0; bool isAlpha = false; // 是否字母的状态标记。 int n = line.length(); for (int i = 0; i < n; ++i){ if (isalpha(line[i])){ if(false == isAlpha){ // 判断字母状态是否由false转向true isAlpha = !isAlpha; ++number; // 转换状态,累计单词数目 } } else{ isAlpha = false; // 不是字母时直接将状态设为false. } } printf("%d\n", number); } return 0; } */
[难度:34] 414 - Machined Surfaces
考英文阅读的简单计算题。
// 414_MachinedSurfaces.cpp /** 414 - Machined Surfaces Time limit: 3.000 seconds Machined Surfaces An imaging device furnishes digital images of two machined surfaces that eventually will be assembled in contact with each other. The roughness of this final contact is to be estimated. A digital image is composed of the two characters, "X" and " " (space). There are always 25 columns to an image, but the number of rows, N, is variable. Column one (1) will always have an "X" in it and will be part of the left surface. The left surface can extend to the right from column one (1) as contiguous X's. Similarly, column 25 will always have an "X" in it and will be part of the right surface. The right surface can extend to the left from column 25 as contiguous X's. Digital-Image View of Surfaces Left Right XXXX XXXXX XXX XXXXXXX XXXXX XXXX XX XXXXXX . . . . . . XXXX XXXX XXX XXXXXX 1 25 In each row of the image, there can be zero or more space characters separating the left surface from the right surface. There will never be more than a single blank region in any row. For each image given, you are to determine the total ``void" that will exist after the left surface has been brought into contact with the right surface. The ``void" is the total count of the spaces that remains between the left and right surfaces after theyhave been brought into contact. The two surfaces are brought into contact by displacing them strictly horizontally towards each other until a rightmost "X" of the left surface of some row is immediately to the left of the leftmost "X" of the right surface of that row. There is no rotation or twisting of these two surfaces as they are brought into contact; they remain rigid, and only move horizontally. Note: The original image may show the two surfaces already in contact, in which case no displacement enters into the contact roughness estimation. Input The input consists of a series of digital images. Each image data set has the following format: First line - A single unsigned integer, N, with value greater than zero (0) and less than 13. The first digit of N will be the first character on a line. Next N lines - Each line has exactly 25 characters; one or more X's, then zero or more spaces, then one or more X's. The end of data is signaled by a null data set having a zero on the first line of an image data set and no further data. Output For each image you receive as a data set, you are to reply with the total void (count of spaces remaining after the surfaces are brought into contact). Use the default output for a single integer on a line. Sample Input (character "B" for ease of reading. The actual input file will use the ASCII-space character, not "B"). 4 XXXXBBBBBBBBBBBBBBBBXXXXX XXXBBBBBBBBBBBBBBBXXXXXXX XXXXXBBBBBBBBBBBBBBBBXXXX XXBBBBBBBBBBBBBBBBBXXXXXX 2 XXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXX 1 XXXXXXXXXBBBBBBBBBBBBBBXX 0 Sample Output 4 0 0 **/ /** * 题目分析: * 还是要先理解题意啊~这一串串的英文,需要学好英语。 * 题目意思是: * 有一个图像,图像由小于13行,25列的元素组成,这些元素会是零,空格,或是"X",图像组成规律是每行的第一列和最后一列一定会有一个X, * 然后,左边的X向右边延展开来,右边的X向左边延展开来,左右两边如果X数目不够,就会用零或者空格来填充满一行二十五格。 * 关键的一段提示是: * For each image given, you are to determine the total ``void" that will exist after the left surface has been brought into contact with the right surface. The ``void" is the total count of the spaces that remains between the left and right surfaces after theyhave been brought into contact. * The two surfaces are brought into contact by displacing them strictly horizontally towards each other until a rightmost "X" of the left surface of some row is immediately to the left of the leftmost "X" of the right surface of that row. There is no rotation or twisting of these two surfaces as they are brought into contact; they remain rigid, and only move horizontally. * 将每一行的X都像中间聚扰,然后空格符放到两边,所谓"void",就是指有最长的那行X减去短行的那些X数目,看看每行可以在这个最长行X范围内剩下多少个空格,这些每个的空格数加起来就是答案了。 * 如:BBBXXXXXXXXBBB // 最长行(X的数目最多) * BBBBXXXXXBBBBB // 这行,相对上一行最长行,少了三个X,即,多了三个空格,此时void为3,将每行的void加起来即为答案 * BBBBBXBBBBBBBB // 这行,相对第一行最长行,少了六个X,即,多了六个空知,此时void+6... * 了解到题目意思后,做起来就简单了: * 1. 分别读取每行的X的元素,记录每行X元素的最大数目。 * 2. 得到多行中拥有最大的X数目的值。 * 3. 然后将这个最大值乘以行数,得到这个“满矩阵”(假如X填满了这些限定范围内的空格的情况下的数目) * 4. 接下来,就用这个总数目,再去减每一行的X值数目,就可以得到剩下的空格数目了。 * 对于第3点,可以这样理解: * 假设原来图形是 BBBBBXXXXXBBBBB * BBBXXXXXXXXBBBB * BBBBBBBXXBBBBBB * 我们可以把多余的B去掉,变为 * BXXXXXXB * XXXXXXXX * BBBBXXBB // 图像2 * 然后,在计算时,将最多X的那行的个数乘以行数就是为了将图像变为 * XXXXXXXX * XXXXXXXX * XXXXXXXX // 图像1 * 结果,就是用图像1的x数目减去图像2的x数目。 **/ #include <cstdio> using namespace std; int main() { unsigned lineNumber; while (EOF != scanf("%d", &lineNumber)){ if (0 == lineNumber) break; unsigned rememberLineNumber = lineNumber; int xNumber[30] = {0}; int maxX = 0; getchar(); while(lineNumber--){ char oneChar; for(int i = 0; i < 25; ++i){ // 输入一行25个字符,分别读取判断 oneChar = getchar(); if ('X' == oneChar){ ++xNumber[lineNumber]; } } getchar(); // 去掉换行符 if (maxX < xNumber[lineNumber]){ maxX = xNumber[lineNumber]; } } maxX = maxX * rememberLineNumber; for (unsigned i = 0; i < rememberLineNumber; ++i){ maxX -= xNumber[i]; } printf("%d\n", maxX); } return 0; }
[难度:42] 490 - Rotating Sentences
字符串输出输出旋转问题,掌握输入输出二维数组顺序的规律即可。
// 490_RotatingSentences.cpp /** 490 - Rotating Sentences Time limit: 3.000 seconds Rotating Sentences In ``Rotating Sentences,'' you are asked to rotate a series of input sentences 90 degrees clockwise. So instead of displaying the input sentences from left to right and top to bottom, your program will display them from top to bottom and right to left. Input and Output As input to your program, you will be given a maximum of 100 sentences, each not exceeding 100 characters long. Legal characters include: newline, space, any punctuation characters, digits, and lower case or upper case English letters. (NOTE: Tabs are not legal characters.) The output of the program should have the last sentence printed out vertically in the leftmost column; the first sentence of the input would subsequently end up at the rightmost column. Sample Input Rene Decartes once said, "I think, therefore I am." Sample Output "R Ie n te h iD ne kc ,a r tt he es r eo fn oc re e s Ia i ad m, . " **/ /** * 题目分析: * 这题的题目要求(90 degrees clockwise)将输入的字符组顺时针旋转90度, * 思路很简单,定义二维数组,输入的时候 先行->后列 输入,输出的时候 先列 -> 后行 输出。 * 下面程序采用了获取字符保存于二维字符数组,然后再将二维数组中的字符提取输出的方法。 * 在输入二组数组的同时,还对数组的行列大小做了一个记录, * 使用lineMaxNumber记录一行里面最大的列数(此时不含下标0),这样,就可以减少输出时循环的次数, * 使用rowArray[]记录每一行的列数,当顺时针90度输出时,将列数与这个每行的列数比较,当其超过记录数,输出空格。 * 使用rowMax记录总行数(含0下标),这样就可以知道整个矩阵的大小了,方便输出的时候可以从最后行开始输出。 * 附:本题WA了很多次,还是不能AC,后来终于发现原因了。。。 * 在 for (row = rowMax - 1; row >= 0; --row)一循环条件中,需要初始化row = rowMax - 1; * 而我在定义的时候,rowMax是已经包含了第零行的了,那为什么还要减一呢? * 后来,个人猜测,这是由于系统的测试数据中,EOF不是放在一行的最后面,而是放在新的一行的最前面 * 即,当测试数据类似于 * testingtestingtesting\n * testingtestingtesting\n * testingtestingtesting\n * EOF * 这时,下面程序中,读取数据的方法是getchar(),如果它将最后一个\n也读取了,那么,实际上,就会多了一行, * 所以下次在做题的时候,注意EOF的位置,是像 * testingtestingtesting\n * testingtestingtestingEOF * 这样,还是在新起一行的开头位置。 **/ #include <cstdio> using namespace std; char cArray[120][120]; int rowArray[120] = {0}; int lineMaxNumber = 0; int main() { int row = 0; int column = 0; char c; while(EOF != (c = getchar())){ if ('\n' == c){ // 遇上换行符时 column = 0; // 列数清零 ++row; // 行数加1 } else{ cArray[row][column++] = c; ++rowArray[row]; // 记录行的字符数(一行有多少列元素) if (rowArray[row] > lineMaxNumber){ lineMaxNumber = rowArray[row]; } } } const int rowMax = row; // 记录最大行数(这里包含了下标0) // 开始timewise(顺时针)旋转90度输出 for (column = 0; column < lineMaxNumber; ++column){ for (row = rowMax - 1; row >= 0; --row){ c = column < rowArray[row] ? cArray[row][column]: ' '; // 当其超过记录的最大列数时,输出空格 printf("%c", c); } printf("\n"); } return 0; } /** // 附: 使用fgets及二维字符数组的做法。 #include <stdio.h> #include <string.h> const int MAX = 120; char array[MAX][MAX]; int main() { int i, j; int lineNumber = 0; int lineLongMax = 0; for ( ;fgets(array[lineNumber], MAX, stdin); ++lineNumber) { if ((i = strlen(array[lineNumber])) > lineLongMax) lineLongMax = i; } for (i = 0; i < lineLongMax - 1; i++) { for (j = lineNumber - 1 ; j >= 0; j--) if (i < strlen(array[j]) - 1){ printf("%c", array[j][i]); } else{ printf(" "); } printf("\n"); } return 0; } **/
[难度:37] 445 - Marvelous Mazes
字符判断及转换的题目。
// 445_MarvelousMazes.cpp /** Marvelous Mazes Your mission, if you decide to accept it, is to create a maze drawing program. A maze will consist of the alphabetic characters A-Z, * (asterisk), and spaces. Input and Output Your program will get the information for the mazes from the input file. This file will contain lines of characters which your program must interpret to draw a maze. Each row of the maze will be described by a series of numbers and characters, where the numbers before a character tell how many times that character will be used. If there are multiple digits in a number before a character, then the number of times to repeat the character is the sum of the digits before that character. The lowercase letter "b" will be used in the input file to represent spaces in the maze. The descriptions for different rows in the maze will be separated by an exclamation point (!)or by an end of line. Descriptions for different mazes will be separated by a blank line in both input and output. The input file will be terminated by an end of file. There is no limit to the number of rows in a maze or the number of mazes in a file, though no row will contain more than 132 characters. Happy mazing! Sample Input 1T1b5T!1T2b1T1b2T!1T1b1T2b2T!1T3b1T1b1T!3T3b1T!1T3b1T1b1T!5T1*1T 11X21b1X 4X1b1X Sample Output T TTTTT T T TT T T TT T T T TTT T T T T TTTTT*T XX X XXXX X **/ /** * 题目分析: * 这是一道字符的输入输出转换题,可以根据题目意思直接变换~直接见注释~ * 另外,这里值得一提的是有一个比较特别的地方,数字的累加,当它是每次都输入数字时,会进行累加, * 当没碰到数字时,则将使用完数字后将数字清零,这是为了让正确地给下一个字符统计数目。 **/ #include <cstdio> #include <cctype> using namespace std; int main() { char c; int times = 0; while(EOF != (c = getchar())){ if(isdigit(c)){ // 是数字时,数值累加 times += (c - '0'); } else if (isupper(c) || c == '*'){ // 迷宫字符 while(times--){ // 输出times个字符 printf("%c", c); } times = 0; } else if ('b' == c){ // 空格 while(times--){ // 输出times个空格 printf(" "); } times = 0; } else{ // 遇到'!'或者'\n'时,都进行换行操作 printf("\n"); times = 0; } } return 0; }
[难度:41] 488 - Triangle Wave
直接依题意做出的简单题,弄清输入输出是什么就可以了。
// 488_TriangleWave.cpp /** 488 - Triangle Wave Time limit: 3.000 seconds Triangle Wave In this problem you are to generate a triangular wave form according to a specified pair of Amplitude and Frequency. Input and Output The input begins with a single positive integer on a line by itself indicating the number of the cases following, each of them as described below. This line is followed by a blank line, and there is also a blank line between two consecutive inputs. Each input set will contain two integers, each on a separate line. The first integer is the Amplitude; the second integer is the Frequency. For each test case, the output must follow the description below. The outputs of two consecutive cases will be separated by a blank line. For the output of your program, you will be printing wave forms each separated by a blank line. The total number of wave forms equals the Frequency, and the horizontal ``height'' of each wave equals the Amplitude. The Amplitude will never be greater than nine. The waveform itself should be filled with integers on each line which indicate the ``height'' of that line. NOTE: There is a blank line after each separate waveform, excluding(不包括) the last one. Sample Input 1 3 2 Sample Output 1 22 333 22 1 1 22 333 22 1 **/ /** * 题目分析: * 这题比较简单,就不累赘了,弄清输入输出是什么就可以, * 输入输出:测试数据组数testCase,测试数据amplitude值--用于确定打印三角形的最值。重复打印Frequency次数。 **/ #include <cstdio> using namespace std; int main() { void print(int am); int testCase; scanf("%d", &testCase); while(testCase--){ // 测试次数输入 int amplitude; int frequency; scanf("%d%d", &litude, &frequency); while(frequency--){ // 重复输出frequency次 print(amplitude); if (0 != frequency){ // 在每个相同的triangular间输出换行,最后一行不输出 printf("\n"); } } if(0 != testCase){ // 在每组数据间输出换行,最后一组不输出 printf("\n"); } } return 0; } void print(int am) { for(int i = 1; i <= am; ++i){ // 从小到大打印 int j = i; while(j--){ printf("%d", i); } printf("\n"); } for(int i = am - 1; i >= 1; --i){ // 从大到小打印 int j = i; while(j--){ printf("%d", i); } printf("\n"); } return; }
[难度:42] 489 - Hangman Judge
两个单词对比的题目,题中有设陷阱,注意重复时不用判断,成功对比时马上退出。
// 489_HangmanJudge.cpp /** Root :: AOAPC I: Beginning Algorithm Contests (Rujia Liu) :: Volume 0. Getting Started 489 - Hangman Judge Time limit: 3.000 seconds Hangman Judge In ``Hangman Judge,'' you are to write a program that judges a series of Hangman games. For each game, the answer to the puzzle is given as well as the guesses. Rules are the same as the classic game of hangman, and are given as follows: 1. The contestant tries to solve to puzzle by guessing one letter at a time. 2. Every time a guess is correct, all the characters in the word that match the guess will be ``turned over.'' For example, if your guess is ``o'' and the word is ``book'', then both ``o''s in the solution will be counted as ``solved.'' 3. Every time a wrong guess is made, a stroke will be added to the drawing of a hangman, which needs 7 strokes to complete. Each unique wrong guess only counts against the contestant once. 4. ______ 5. | | 6. | O 7. | /|\ 8. | | 9. | / \ 10. __|_ 11. | |______ |_________| 12. If the drawing of the hangman is completed before the contestant has successfully guessed all the characters of the word, the contestant loses. 13. If the contestant has guessed all the characters of the word before the drawing is complete, the contestant wins the game. 14. If the contestant does not guess enough letters to either win or lose, the contestant chickens out. Your task as the ``Hangman Judge'' is to determine, for each game, whether the contestant wins, loses, or fails to finish a game. Input Your program will be given a series of inputs regarding the status of a game. All input will be in lower case. The first line of each section will contain a number to indicate which round of the game is being played; the next line will be the solution to the puzzle; the last line is a sequence of the guesses made by the contestant. A round number of -1 would indicate the end of all games (and input). Output The output of your program is to indicate which round of the game the contestant is currently playing as well as the result of the game. There are three possible results: You win. You lose. You chickened out. Sample Input 1 cheese chese 2 cheese abcdefg 3 cheese abcdefgij -1 Sample Output Round 1 You win. Round 2 You chickened out. Round 3 You lose. **/ /** * 题目大意: * 先输入第几回合(改变一下格式输出,对计算无影响),再输入两个单词,假设第一个单词叫做first, * 第二个单词叫做second,那么,将second中的每个字符与first比较,假如,second单词能从下标最小到最大 * 与first中的单词字符比较: * 1. 不管是first还是second,只要有重复的字符,都不列入比较次数内。 * 2. 假如在比较过程中,比较了七次或以上还是没有将first的全部字符比较出来(即second中有first中的全部字母)。 * 那么,就输出 You lose. * 3. 如果在七次内,将全部字符比较出来,就输出You win. * 4. 如果在七次内,但又未将first中的全部字符比较出来,second就遍历完了,那么就输出 You chickened out. * * 题目分析: * 1. 先按要求,输入三个数据,int, string1, string2; * 2. 去除string1和string2的重复字母。 * 3. 将string2中的字符(从下标最小到最大)逐个与string1中的字符比较,查看是否有相同字符。 * 存在相同字符:win计数加1, 如果win达到string1的长度,输出 You win. 退出全部循环,继续下一轮比赛。 * 没有相同字符:lose计数加1,如果lose达到7,输出 You lose.退出全部循环,继续下一轮比赛。 * 4. 比较结束后,还会有一种情况,当win计数未达string1的长度且lose计数小于7时,输出 You chickened out. * 5. 注意:当round == -1 时,结束程序。 **/ #include <string> #include <cstring> #include <iostream> #include <cstdio> using namespace std; int main() { int round; while(scanf("%d", &round) && round != -1){ printf("Round %d\n", round); // 按题目要求,打印“第几轮比赛” string hangman; string contestant; cin >> hangman >> contestant; // 继续输入,两个字符串 string deleteTheSameInString(string); // 删除重复字符 hangman = deleteTheSameInString(hangman); contestant = deleteTheSameInString(contestant); const int nh = hangman.length(); const int nc = contestant.length(); int winCount = 0; int loseCount = 0; for(int i = 0; i < nc; ++i){ bool noSame = true; for (int j = 0; j < nh; ++j){ // contesant的单个字母与hangman内的全部字符比较 if (contestant[i] == hangman[j]){ if (++winCount == nh){ printf("You win.\n"); i = nc; // 让其跳出外部循环(这步很容易忽略) } noSame = false; break; } } if (noSame){ if(7 <= ++loseCount){ // 超出猜的机会 printf("You lose.\n"); break; } } } if (winCount != nh && 7 > loseCount){ // 未全部猜出而且还有猜的机会 printf("You chickened out.\n"); } } return 0; } string deleteTheSameInString(string source) { string copyString; int n = source.length(); for (int i = 0; i < n; ++i){ if(' ' != source[i]){ // 非空白字符则将其加入字符串 copyString.push_back(source[i]); } else{ continue; // 发现空白字符,可以继续下一轮的循环 } int copyStringLastIndex = copyString.length() - 1; for (int j = i + 1; j < n; ++j){ if (copyString[copyStringLastIndex] == source[j]){ source[j] = ' '; // 发现重复的字符则将其换为' ' } } } return copyString; }
[难度:64] 694 - The Collatz Sequence
类似于3n+1的题目,不过这道题目简化了,依据题目意思去写程序就可以了。
// 694_TheCollatzSequence.cpp /** Root :: AOAPC I: Beginning Algorithm Contests (Rujia Liu) :: Volume 0. Getting Started 694 - The Collatz Sequence Time limit: 3.000 seconds The Collatz Sequence An algorithm given by Lothar Collatz produces sequences of integers, and is described as follows: Step 1: Choose an arbitrary positive integer A as the first item in the sequence. Step 2: If A = 1 then stop. Step 3: If A is even, then replace A by A / 2 and go to step 2. Step 4: If A is odd, then replace A by 3 * A + 1 and go to step 2. It has been shown that this algorithm will always stop (in step 2) for initial values of A as large as 109, but some values of A encountered in the sequence may exceed the size of an integer on many computers. In this problem we want to determine the length of the sequence that includes all values produced until either the algorithm stops (in step 2), or a value larger than some specified limit would be produced (in step 4). Input The input for this problem consists of multiple test cases. For each case, the input contains a single line with two positive integers, the first giving the initial value of A (for step 1) and the second giving L, the limiting value for terms in the sequence. Neither of these, A or L, is larger than 2,147,483,647 (the largest value that can be stored in a 32-bit signed integer). The initial value of A is always less than L. A line that contains two negative integers follows the last case. Output For each input case display the case number (sequentially numbered starting with 1), a colon, the initial value for A, the limiting value L, and the number of terms computed. Sample Input 3 100 34 100 75 250 27 2147483647 101 304 101 303 -1 -1 Sample Output Case 1: A = 3, limit = 100, number of terms = 8 Case 2: A = 34, limit = 100, number of terms = 14 Case 3: A = 75, limit = 250, number of terms = 3 Case 4: A = 27, limit = 2147483647, number of terms = 112 Case 5: A = 101, limit = 304, number of terms = 26 Case 6: A = 101, limit = 303, number of terms = 1 ________________________________________ Miguel Revilla 2000-08-14 **/ /** * 题目大意:(这题实质上与3n+1题型相似) * 输入A和L两个不超过32位的int类型的数值,遵循以下规则: * 1. 当A = 1,停止计算。 * 2. 当A为偶数,A = A / 2; * 3. 当A为奇数,A = A * 3 + 1, A > L 时,不合题意,停止计算并且该次计算不放入计算次数内。; * 4. 当用2和3的计算方法计算得出的结果与历史的结果(每次A运行后的结果)相同时,停止计算。 * * 题目分析: * 根据题目意思,初始化时,将count初始化为1,因为第一步就是指获取A这个数, * 然后,当成功执行A = A / 2时,计数count + 1; * 接下来,如果成功执行 A = A * 3 + 1 且 A还在L的范围内时,计数count + 1; * 一直运算,直到符合上面所说的三个停止运行条件,即可停止循环,输出count的结果。 **/ #include <cstdio> #include <vector> using namespace std; int main() { int testCase = 1; int A, L; while(scanf("%d%d", &A, &L) && (A != -1 || L != -1)){ printf("Case %d: A = %d, limit = %d, number of terms = ", testCase++, A, L); int count = 1; int result = A; vector<int> saveResult; saveResult.push_back(A); // 把A也放进去result组里面,那么在while判断的时候就不用判断这点了 bool notHaveSame(true); while(notHaveSame){ if (0 == result % 2){ // Even result = result / 2; ++count; if(result == 1) { break;} } else{ // Odd result = result * 3 + 1; if(result > L || result < 1) { break; } // 越界或者溢出 else { ++count;} } int n = saveResult.size(); for (int i = 0; i < n; ++i){ if (saveResult[i] == result){ notHaveSame = false; break; } } saveResult.push_back(result); } printf("%d\n", count); } return 0; }
[难度:38] 457 - Linear Cellular Automata
考英文阅读的二维数组输入输出加上简单的数学计算组合题。
// 457_LinearCellularAutomata.cpp /** Root :: AOAPC I: Beginning Algorithm Contests (Rujia Liu) :: Volume 0. Getting Started 457 - Linear Cellular Automata Time limit: 3.000 seconds Linear Cellular Automata A biologist is experimenting with DNA modification of bacterial colonies being grown in a linear array of culture dishes. By changing the DNA, he is able ``program" the bacteria to respond to the population density of the neighboring dishes. Population is measured on a four point scale (from 0 to 3). The DNA information is represented as an array DNA, indexed from 0 to 9, of population density values and is interpreted as follows: In any given culture dish, let K be the sum of that culture dish's density and the densities of the dish immediately to the left and the dish immediately to the right. Then, by the next day, that dish will have a population density of DNA[K]. The dish at the far left of the line is considered to have a left neighbor with population density 0. The dish at the far right of the line is considered to have a right neighbor with population density 0. Now, clearly, some DNA programs cause all the bacteria to die off (e.g., [0,0,0,0,0,0,0,0,0,0]). Others result in immediate population explosions (e.g., [3,3,3,3,3,3,3,3,3,3]). The biologist is interested in how some of the less obvious intermediate DNA programs might behave. Write a program to simulate the culture growth in a line of 40 dishes, assuming that dish 20 starts with a population density of 1 and all other dishes start with a population density of 0. Input The input begins with a single positive integer on a line by itself indicating the number of the cases following, each of them as described below. This line is followed by a blank line, and there is also a blank line between two consecutive inputs. For each input set your program will read in the DNA program (10 integer values) on one line. Output For each test case, the output must follow the description below. The outputs of two consecutive cases will be separated by a blank line. For each input set it should print the densities of the 40 dishes for each of the next 50 days. Each day's printout should occupy one line of 40 characters. Each dish is represented by a single character on that line. Zero population densities are to be printed as the character ` '. Population density 1 will be printed as the character `.'. Population density 2 will be printed as the character `x'. Population density 3 will be printed as the character `W'. Sample Input 1 0 1 2 0 1 3 3 2 3 0 Sample Output bbbbbbbbbbbbbbbbbbb.bbbbbbbbbbbbbbbbbbbb bbbbbbbbbbbbbbbbbb...bbbbbbbbbbbbbbbbbbb bbbbbbbbbbbbbbbbb.xbx.bbbbbbbbbbbbbbbbbb bbbbbbbbbbbbbbbb.bb.bb.bbbbbbbbbbbbbbbbb bbbbbbbbbbbbbbb.........bbbbbbbbbbbbbbbb bbbbbbbbbbbbbb.xbbbbbbbx.bbbbbbbbbbbbbbb bbbbbbbbbbbbb.bbxbbbbbxbb.bbbbbbbbbbbbbb bbbbbbbbbbbb...xxxbbbxxx...bbbbbbbbbbbbb bbbbbbbbbbb.xb.WW.xbx.WW.bx.bbbbbbbbbbbb bbbbbbbbbb.bbb.xxWb.bWxx.bbb.bbbbbbbbbbb Note: Whe show only the first ten lines of output (the total number of lines must be 50) and the spaces have been replaced with the character "b" for ease of reading. The actual output file will use the ASCII-space character, not "b". **/ /** * 题目大意: * 这道题理解好英语其实一点也不难做,它说DNA信息以细菌密度值的DNA数列表示,编号从0到9。 * 然后,观察50天,看看变化情况,而这些培养皿中,会有四种细菌密度大小,分别定义它们为0, 1, 2, 3。 * 此外: * 特别要注意理解这一句:(整个计算算法的核心内容) * In any given culture dish, let K be the sum of that culture dish's density and the densities of the dish immediately to * the left and the dish immediately to the right. * Then, by the next day, that dish will have a population density of DNA[K]. * 假设K是该培养皿、该培养皿最靠近的左边的以及最靠近的右边的细菌密度的值之和为K, * 则第二天,该培养皿的细菌密度为 DNA[K]. * 现在写一个有40个培养皿的程序,然后观察50天,并且初始化第一天的第20个培养皿为1, 其它都为0 * 输入:先是输入一个整型数据用以测试用例的数量。然后输入10个DNA程式(相当于DNA[k]数组中的元素). * 输出:密度0对应' ',密度大小1对应'.', 密度大小2对应'x', 密友大小3对应'W',每两个用例用空行间开。 * * 思路分析: * 1. 先确定输入的案例数目,使用循环,控制运行案例次数。 * 2. 输入这10个DNA程式,然后,因为在计算时需要用到int型数据,在输出时需要用到char型数据, * 所以,在下面的程序中,就直接定义了两个数组了,一个是关于这个DNA程式的int型数组,一个是对应的char型。 * 3. 然后,先初始化并输出第一行的对应DNA密度,这是因为这是每个案例中固定好不变的输出,所以可以先对其进行处理。 * 4. 接下来,按照上面的那串英文的规律,对dish数组进行赋值,这时,行下标是(0~49)(0已被初始化) * 列下标是(1~50),采用1开始做列下标,是因为,方便运算,在计算时[row]时,需要用上[row-1]的左右和本身数据, * 如果将列下标设为1开始,就免去对原来下标为0的处理的麻烦(即如果是0~49,需要考虑溢出情况),同理 * 到列下标为50时,因为将数组初始化时初始化得比50要大,所以,也免去了这个处理溢出的麻烦。 * 5. 最后,在计算的同时,进行输出。 * 6. 需要注意的一点是,假如是最后一个用例,用例完成后,不用输出空行。 **/ #include <stdio.h> #include <string.h> const int maxRow = 50; const int maxColumn = 40; int dish[maxRow + 10][maxColumn + 10]; int dnaI[10]; char dnaC[10]; int main() { int testCase; scanf("%d", &testCase); while(testCase--){ // construct the dna array for ( int k = 0; k < 10; ++k){ scanf("%d", &dnaI[k]); switch(dnaI[k]){ case 0: dnaC[k] = ' '; break; case 1: dnaC[k] = '.'; break; case 2: dnaC[k] = 'x'; break; case 3: dnaC[k] = 'W'; break; } } // print the first line for (int column = 1; column <= 19; ++column){ // 打印第一行的全部列(左边) printf(" "); } printf("."); for (int column = 21; column <= maxColumn; ++column){ // 打印第一行的全部列(右边) printf(" "); } printf("\n"); // start the dish project memset(dish, 0, sizeof(dish)); dish[0][20] = 1; // construct the dish array for (int row = 1; row < maxRow; ++row){ for(int column = 1; column <= maxColumn; ++column){ // 从下标1开始,不用考虑最左最右界限的问题 int temp = dish[row-1][column+1] + dish[row-1][column-1] + dish[row-1][column]; // 计算完毕后,可以开始打印该字符 printf("%c", dnaC[ temp ] ); // 打印DNA dish[row][column] = dnaI[ temp ]; // 转成DNA } printf("\n"); // 40个字符满一行,输出换行符 } if (0 != testCase){ printf("\n"); // 每个案例间用换行符间开,除了最后一个案例。 } } return 0; }