当前位置:   article > 正文

《算法竞赛入门经典-第二版》第三章习题答案_算法竞赛入门经典第二版答案pdf

算法竞赛入门经典第二版答案pdf

       《算法竞赛入门经典-第二版》课后习题答案

                                   第三章(未更完)

         习题3-1 得分(Score, ACM/ICPC Seoul 2005, UVa1585)

         给出一个由O和X组成的串(长度为1~80),统计得分。每个O的得分为目前连续出现的O的个数,X的得分为0。例如,OOXXOXXOOO的得分为1+2+0+0+1+0+0+1+2+3。

  1. #include<stdio.h>
  2. #include <string.h>
  3. #define maxn 85
  4. int main() {
  5. int number,tot = 0,numx=0;
  6. char s[maxn];
  7. scanf("%d",&number);
  8. while(number--){
  9. tot=0;
  10. numx=0;
  11. scanf("%s", s);
  12. for(int i = 0; i < strlen(s); i++){
  13. if(s[i] == 'O') tot=++numx+tot;
  14. else if (s[i] == 'X') numx=0;
  15. }
  16. printf("%d\n", tot);
  17. }
  18. }

        习题3-2 分子量(Molar Mass, ACM/ICPC Seoul 2007, UVa1586)

         给出一种物质的分子式(不带括号),求分子量。本题中的分子式只包含4种原子,分别为C, H, O, N,原子量分别为12.01, 1.008, 16.00, 14.01(单位:g/mol)。例如,C6H5OH的分子量为94.108g/mol。

  1. #include<stdio.h>
  2. #include <string.h>
  3. #define maxn 85
  4. int main() {
  5. int T,flag,num=0;
  6. char s[maxn];
  7. int result[4];
  8. //进行判定的分子式数目
  9. scanf("%d",&T);
  10. while(T--){
  11. //结果数组赋初值
  12. memset(result,0, sizeof(result));
  13. scanf("%s", s);
  14. for(int i = 0; i < strlen(s); i++){
  15. switch(s[i]){
  16. case 'C':
  17. flag=0;
  18. break;
  19. case 'H':
  20. flag=1;
  21. break;
  22. case 'O':
  23. flag=2;
  24. break;
  25. case 'N':
  26. flag=3;
  27. break;
  28. }
  29. //num表示该元素的个数
  30. num=0;
  31. //如果该元素接下来的字符是数字将计算个数,否则个数等于1
  32. while(s[i+1]>=48 &&s[i+1]<=57){
  33. ++i;
  34. num=num*10+(s[i]-'0');
  35. }
  36. if(num==0) num=1;
  37. result[flag]= result[flag]+num;
  38. }
  39. //结果输出
  40. printf("%.3f\n", result[0]*12.01+1.008*result[1]+result[2]*16.00+result[3]*14.01);
  41. }
  42. }
'
运行

        习题3-3 数数字(Digit Counting , ACM/ICPC Danang 2007, UVa1225)

         把前n(n≤10000)个整数顺次写在一起:123456789101112…数一数0~9各出现多少次(输出10个整数,分别是0,1,…,9出现的次数)

  1. #include<stdio.h>
  2. #include <string.h>
  3. int main() {
  4. int T,number,numcount[10];
  5. scanf("%d",&T);
  6. while(T--){
  7. memset(numcount,0, sizeof(numcount));
  8. scanf("%d",&number);
  9. for (int i = 1; i <= number; i++) {
  10. int flag=i;
  11. //先将末位数字计数之后一步一步将十位百位计数
  12. while (flag>=10){
  13. numcount[flag%10]++;
  14. flag=flag/10;
  15. }
  16. numcount[flag]++;
  17. }
  18. //结果输出,最后一个数据输出之后不含空格直接换行
  19. for (int j = 0; j <9 ; j++) {
  20. printf("%d ",numcount[j]);
  21. }
  22. printf("%d\n",numcount[9]);
  23. }
  24. }

        习题3-4 周期串(Periodic Strings, UVa455)

        如果一个字符串可以由某个长度为k的字符串重复多次得到,则称该串以k为周期。例如,abcabcabcabc以3为周期(注意,它也以6和12为周期)。输入一个长度不超过80的字符串,输出其最小周期。

  1. #include<stdio.h>
  2. #include <string.h>
  3. #define maxn 85
  4. bool IsPs(const char* s, int p){
  5. //p将s分成strlen(s)/p段,判断每个段中的第i个数是否相等。
  6. for (int i = 0; i <p ; i++) {
  7. for (int j = 0; j <strlen(s)/p-1 ; j++) {
  8. if(s[j*p+i]!=s[(j+1)*p+i]) return false;
  9. }
  10. }
  11. return true;
  12. }
  13. int main() {
  14. int T;
  15. char s[maxn];
  16. scanf("%d",&T);
  17. while(T--){
  18. scanf("%s",s);
  19. int length = strlen(s);
  20. //从1到k判断字符串是否以i为周期
  21. for (int i = 1; i <=length; i++)
  22. {
  23. //s不能整除i,肯定不以i为周期,跳过循环。
  24. if(length%i!=0) continue;
  25. //判断以s是否以i为周期,是的话结果输出
  26. if(IsPs(s,i))
  27. {
  28. printf("%d\n", i);
  29. if (T) printf("\n");
  30. break;
  31. }
  32. }
  33. }
  34. }

习题3-5 谜题(Puzzle, ACM/ICPC World Finals 1993, UVa227)

有一个5*5的网格,其中恰好有一个格子是空的,其他格子各有一个字母。一共有4种指令:A, B, L, R,分别表示把空格上、下、左、右的相邻字母移到空格中。输入初始网格和指令序列(以数字0结束),输出指令执行完毕后的网格。如果有非法指令,应输出“Thispuzzle has no final configuration.”,例如,图3-5中执行ARRBBL0后,效果如图3-6所示。

输入:

AAAAA
DDDDD
SSSSS
GGGGG
EEEE 
AZ
0
AAAAA
DDDDD
SSSSS
GGGGG
EEEE 
A0
Z

预期输出:

Puzzle #1:
This puzzle has no final configuration.

Puzzle #2:
A A A A A
D D D D D
S S S S S
G G G G  
E E E E G

输入直接用scanf(%s,s)当有空格的时候就会停止读入导致空格读取不上,

 输出格式要注意很容易出现格式错误。

  1. #include<stdio.h>
  2. int main() {
  3. char s[5][10];
  4. int line =0,row=0,count =0 ;
  5. while (1){
  6. //读取数组的值
  7. for (int i = 0; i <5 ; i++)
  8. {
  9. scanf("%[^\n]%*c",s[i]);
  10. if(s[i][0]=='Z') return 0;
  11. for (int j = 0; j <5 ; j++) {
  12. //找到空值的位置
  13. if(s[i][j]==' ')
  14. {
  15. line=i;
  16. row=j;
  17. }
  18. }
  19. }
  20. bool flag= true;
  21. char c;
  22. //对指令依次进行判断是否能执行
  23. while((c=getchar())!='0'){
  24. //前面已经有指令已经不能执行,后面的代码就没必要执行了
  25. if(!flag)continue;
  26. //判断指令能否执行
  27. switch(c){
  28. case 'A':
  29. if(line-1>=0){
  30. s[line][row]=s[line-1][row];
  31. s[--line][row]=' ';
  32. }
  33. else flag=false;
  34. break;
  35. case 'B':
  36. if(line+1<5){
  37. s[line][row]=s[line+1][row];
  38. s[++line][row]=' ';
  39. }
  40. else flag=false;
  41. break;
  42. case 'L':
  43. if(row-1>=0){
  44. s[line][row]=s[line][row-1];
  45. s[line][--row]=' ';
  46. }
  47. else flag=false;
  48. break;
  49. case 'R':
  50. if(row+1<5){
  51. s[line][row]=s[line][row+1];
  52. s[line][++row]=' ';
  53. }
  54. else flag=false;
  55. break;
  56. case '\n':
  57. break;
  58. default:
  59. flag=false;
  60. break;
  61. }
  62. }
  63. //通过getchar函数将\n去掉
  64. getchar();
  65. //结果输出
  66. if(count!=0)printf("\n");
  67. printf("Puzzle #%d:\n",++count);
  68. if(flag){
  69. for (int i = 0; i < 5; i++) {
  70. for (int j = 0; j <4 ; j++) {
  71. putchar(s[i][j]);
  72. putchar(' ');
  73. }
  74. putchar(s[i][4]);
  75. putchar('\n');
  76. }
  77. }
  78. else printf("This puzzle has no final configuration.\n");
  79. }
  80. }

习题3-6 纵横字谜的答案(Crossword Answers, ACM/ICPC World Finals 1994,UVa232)

       输入一个r行c列(1≤r,c≤10)的网格,黑格用“*”表示,每个白格都填有一个字母。如果一个白格的左边相邻位置或者上边相邻位置没有白格(可能是黑格,也可能出了网格边界),则称这个白格是一个起始格。首先把所有起始格按照从上到下、从左到右的顺序编号为1, 2, 3,…,如图3-7所示。

         

           接下来要找出所有横向单词(Across)。这些单词必须从一个起始格开始,向右延伸到一个黑格的左边或者整个网格的最右列。最后找出所有竖向单词(Down)。这些单词必须从一个起始格开始,向下延伸到一个黑格的上边或者整个网格的最下行。

本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号