3.1数组

数组较大

比较大的数组尽量声明在main函数外,否则程序可能无法进行。

数组操作

如果要从数组a复制k个元素到数组b,可以这样做:memcpy(b,a,sizeof(int)*k)。 
如果数组a和b都是浮点型的,复制时要写成memcpy(b,a,sizeof(double)*k)。 
另外需要注意的是, 使用memcpy函数要包含头文件string.h。 
如果需要把数组a全部复制到数组b中,可以写得简单 一些:memcpy(b,a,sizeof(a))

开灯问题

有n盏灯,编号为1~n。第1个人把所有灯打开,第2个人按下所有编号为2的倍数的开关(这些灯将被关掉),第3个人按下所有编号为3的倍数的开关(其中关掉的灯将被打开,开着的灯将被关闭),依此类推。一共有k个人,问最后有哪些灯开着?输入n和k,输出开着的灯的编号。k≤n≤1000。 
样例输入: 
7 3 
样例输出: 
1 5 6 7

#include<stdio.h>
#include<string.h>
#define maxn 1010  //在算法竞赛中,难以精确计算出需要的数组大小,数组一般会声明的稍大一些。
int a[maxn];
int main()
{  int n,k,first=1;  //first变量可以表示当前要输出的变量是否为第一个。第一个变量前不应有空格,但其他变量都有。memset(a,0,sizeof(a));  //把数组a清零 scanf("%d%d",&n,&k);  //n盏灯,k个人 for(int i=1;i<=k;i++)for(int j=1;j<=n;j++)if(j%i==0)   //判断是k的倍数a[j]=!a[j];for(int i=1;i<=n;i++)if(a[i]){if(first)   first=0;else    printf(" ");printf("%d",i);} printf("\n");return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

蛇形填数

在n×n方阵里填入1,2,…,n×n,要求填成蛇形。例如,n=4时方阵为: 
10 11 12 1 
9 16 13 2 
8 15 14 3 
7 6 5 4 
上面的方阵中,多余的空格只是为了便于观察规律,不必严格输出。n≤8。

#include<stdio.h>
#include<string.h>
#define maxn 20
int a[maxn][maxn];
int main()
{  int n,x,y,tot=0;scanf("%d",&n);memset(a,0,sizeof(a));//把数组a清零 tot=a[x=0][y=n-1]=1;while(tot<n*n)  //判断是否填满 {while(x+1<n && !a[x+1][y])  a[++x][y]=++tot;//判断是否越界 向下 while(y-1>=0 && !a[x][y-1]) a[x][--y]=++tot;//判断是否越界 向左 while(x-1>=0 && !a[x-1][y]) a[--x][y]=++tot;//判断是否越界 向上 while(y+1<n && !a[x][y+1])  a[x][++y]=++tot;//判断是否越界 向右 }for(x=0;x<n;x++){for(y=0;y<n;y++)printf("%3d",a[x][y]);printf("\n");}return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29

3.2字符数组

竖式问题

找出所有形如abc*de(三位数乘以两位数)的算式,使得在完整的竖式中, 所有数字都属于一个特定的数字集合。输入数字集合(相邻数字之间没有空格),输出所有竖式。每个竖式前应有编号,之后应有一个空行。最后输出解的总数。具体格式见样例输出 (为了便于观察,竖式中的空格改用小数点显示,但所写程序中应该输出空格,而非小数点)。

样例输入:
2357
样例输出:
<1>
..775
X..33
----
.2325
2325.
----
25575
The number of solutions = 1
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
#include<stdio.h>
#include<string.h>
int main()
{  int count=0;printf("%d%d%d",count++,count++,count++);char s[20],buf[99]; scanf("%s",s);for(int abc=111;abc<=999;abc++)for(int de=11;de<=99;de++){int x=abc*(de%10),y=abc*(de/10),z=abc*de;  //x为abc乘以de的个位,y为abc乘以de的十分位,z为abc乘以de的和 sprintf(buf,"%d%d%d%d%d",abc,de,x,y,z); //printf输出到屏幕,fprintf输出到文件,而sprintf输出到字符串 int ok=1;for(int i=0;i<strlen(buf);i++)//函数strlen(s)的作用是获取字符串s的实际长度if(strchr(s,buf[i])==NULL)  //strchr的作用是在一个字符串中查找单个字符{ok=0;break;  //跳出循环 }    if(ok){printf("<%d>\n",++count);printf("%5d\nX%4d\n-----\n%5d\n%4d\n-----\n%5d\n\n",abc,de,x,y,z);}} printf("The number of solutions = %d\n",count);return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29

输入字符串

scanf("%s", s)scanf("%d", &n)类似,它会读入一个不含空格、 TAB和回车符的字符串,存入字符数组s。注意,不是scanf("%s", &s),s前面没有“&”符 号。 
scanf("%s", s)中,不要在s前面加上“&”符号。如果是字符串数组char s[maxn] [maxl],可以用scanf("%s", s[i])读取第i个字符串。注意,scanf("%s", s)遇到空白字符会停下来。

printf,fprintf,sprintf的区别

printf输出到屏幕 
fprintf输出到文件 
sprintf输出到字符串 
可以用sprintf把信息输出到字符串,用法和printf、fprintf类似。但应当保 证字符串足够大,可以容纳输出信息。 
多大才算足够大呢?答案是字符个数加1,因为C语言的字符串是以空字符“\0”结尾的。

字符串函数

C语言中的字符串是以“\0”结尾的字符数组,可以用strlen(s)返回字符串s中结束标记之前的字符个数。字符串中的各个字符是s[0], s[1],…,s[strlen(s)-1]。 
由于字符串的本质是数组,只能用strcpy(a, b), strcmp(a, b), strcat(a, b)来执行“赋值”、“比较”和“连接”操作,而不能用“=”、“==”、 “<=”、“+”等运算符。上述函数都在string.h中声明。 
如果输入是“2357”,那么实际上s只保存了5个字符(不 忘记了还有一个结束标记“\0”),后面15个字符是不确定的(还记得吗?变量在赋值之前是不确定的)。strlen(s)返回的就是结束标记之前的字符个数。因此这个字符串中的各个字符依次是s[0], s[1],…, s[strlen(s)-1],而s[strlen(s)]正是结束标记\0

3.3竞赛题目选讲

例题3-1 TeX中的引号(Tex Quotes, UVa 272)

在TeX中,左双引号是““”,右双引号是“””。输入一篇包含双引号的文章,你的任务是把它转换成TeX的格式。 
样例输入:

"To be or not to be," quoth the Bard, "that is the question".
  • 1

样例输出:

``To be or not to be,'' quoth the Bard, ``that is the question''.
  • 1
#include<stdio.h>
int main()
{  int c,q=1;while((c=getchar())!=EOF) //用getchar()可以边读边处理,而不需要把输入字符串完整地存下来{if(c=='"'){printf("%s",q?"``":"''");q=!q;}elseprintf("%c",c);}return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

例题3-2 WERTYU(WERTYU, UVa10082)

把手放在键盘上时,稍不注意就会往右错一位。这样,输入Q会变成输入W,输入J会变成输入K等。 
输入一个错位后敲出的字符串(所有字母均大写),输出打字员本来想打出的句子。输入保证合法,即一定是错位之后的字符串。例如输入中不会出现大写字母A。 
样例输入: 
O S, GOMR YPFSU/ 
样例输出: 
I AM FINE TODAY. 

#include<stdio.h>
char s[]="`1234567890-=QWERTYUIOP[]\\ASDFGHJKL;'ZXCVBNM,./"; //输入保证合法,所以可以使用这个方法,否则还要判断
int main()
{  int i,c;while((c=getchar())!=EOF){for(i=1;s[i]&&s[i]!=c;i++); //找错位之后的字符在常量表中的位置if(s[i])    putchar(s[i-1]); //如果找到,则输出它的前一个字符else putchar(c); }return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

例题3-3 回文词(Palindromes, UVa401)

输入一个字符串,判断它是否为回文串以及镜像串。输入字符串保证不含数字0。所谓回文串,就是反转以后和原串相同,如abba和madam。所有镜像串,就是左右镜像之后和原串相同,如2S和3AIAE。注意,并不是每个字符在镜像之后都能得到一个合法字符。在本题中,每个字符的镜像如图3-3所示(空白项表示该字符镜像后不能得到一个合法字符)。 
 
输入的每行包含一个字符串(保证只有上述字符。不含空白字符),判断它是否为回文串和镜像串(共4种组合)。每组数据之后输出一个空行。

样例输入:
NOTAPALINDROME
ISAPALINILAPASI
2A3MEAS
ATOYOTA
样例输出:
NOTAPALINDROME -- is not a palindrome.
ISAPALINILAPASI -- is a regular palindrome.
2A3MEAS -- is a mirrored string.
ATOYOTA -- is a mirrored palindrome.
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
#include<stdio.h>
#include<string.h>
#include<ctype.h>
const char* rev="A   3  HIL JM O   2TUVWXY51SE Z  8 ";
const char* msg[]={"not a palindrome","a regular palindrome",
"a mirrored string","a mirrored palindrome"};char r(char ch)
{if(isalpha(ch))  //判断字符是否为字母,需要添加头文件#include<ctype.h>return rev[ch - 'A'];return rev[ch - '0' + 25];
}
int main()
{  char s[30];while(scanf("%s",s)==1){int len=strlen(s);int p=1,m=1;for(int i=0;i<(len+1)/2;i++){if(s[i]!=s[len-1-i])p=0;//不是回文串if(r(s[i])!=s[len-1-i])m=0;//不是镜像串 }printf("%s -- is %s.\n\n",s,msg[m*2+p]); }return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

头文件ctype.h

头文件ctype.h中定义的isalpha、isdigit、isprint等工具可以用来判断字符的属性,而toupper、tolower等工具可以用来转换大小写。如果ch是大写字母,则ch-‘A’就是它在字母表中的序号(A的序号是0,B的序号是1,依此类推);类似地,如果ch是数字, 则ch-‘0’就是这个数字的数值本身。

例题3-4 猜数字游戏的提示(Master-Mind Hints, UVa 340)

实现一个经典”猜数字”游戏。给定答案序列和用户猜的序列,统计有多少数字位置正确 (A),有多少数字在两个序列都出现过但位置不对(B)。 
输入包含多组数据。每组输入第一行为序列长度n,第二行是答案序列,接下来是若干猜测序列。猜测序列全0时该组数据结束。n=0时输入结束。

样例输入:
4
1 3 5 5
1 1 2 3
4 3 3 5
6 5 5 1
6 1 3 5
1 3 5 5
0 0 0 0
10
1 2 2 2 4 5 6 6 6 9
1 2 3 4 5 6 7 8 9 1
1 1 2 2 3 3 4 4 5 5
1 2 1 3 1 5 1 6 1 9
1 2 2 5 5 5 6 6 6 7
0 0 0 0 0 0 0 0 0 0
0
样例输出:
Game 1:  (1,1)    (2,0)    (1,2)    (1,2)    (4,0)
Game 2:    (2,4)(3,2)    (5,0)    (7,0)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
#include<stdio.h>
#define maxn 1010
int main()
{  int n,a[maxn],b[maxn];int kase=0;while(scanf("%d",&n)==1&&n)  //n=0时输入结束 ,n为序列长度 {printf("Game %d:\n",++kase);for(int i=0;i<n;i++)   //答案序列a scanf("%d",&a[i]);for(;;) {int A=0,B=0;for(int i=0;i<n;i++) //猜测序列b {scanf("%d",&b[i]);if(a[i]==b[i]) //数字和位置都正确的个数A A++;}if(b[0]==0)break;//正常的猜测序列中不会有0,所以只判断第一个数是否为0即可for(int d=1;d<=9;d++)  //为了求B,对于每个数字(1~9),统计二者出现的次数c1和c2,则 min(c1,c2)就是该数字对B的贡献,最后要减去A的部分{int c1=0,c2=0;//统计数字d在答案序列和猜测序列中各出现多少次for(int i=0;i<n;i++) {if(a[i]==d)c1++;if(b[i]==d)c2++;} if(c1<c2)B+=c1;elseB+=c2;} printf("   (%d,%d)\n",A,B-A);}}return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42

例题3-5 生成元(Digit Generator, ACM/ICPC Seoul 2005, UVa1583)

如果x加上x的各个数字之和得到y,就说x是y的生成元。给出n(1≤n≤100000),求最小生成元。无解输出0。例如,n=3,输入216,121,2005时的解分别为198,0,1979。

#include<stdio.h>
#include<string.h>
#define maxn 100005
int ans[maxn];
int main()
{  int T,n;memset(ans,0,sizeof(ans));for(int m=1;m<maxn;m++){int x=m,y=m;while(x>0){y+=x%10; //y为生成元 x/=10;}if(ans[y]==0||m<ans[y]) ans[y]=m; //m加上m的各个数字之和得到的数有一个生成元是y }scanf("%d",&T);  //没有特别理解这句话的含义,感觉就是可以重复输入三个n值 while(T--){scanf("%d",&n);printf("%d\n",ans[n]);}return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

例题3-6 环状序列(Circular Sequence, ACM/ICPC Seoul 2004, UVa1584)

长度为n的环状串有n种表示法,分别为从某个位置开始顺时针得到。例如,图3-4的环状串有10种表示: 
CGAGTCAGCT,GAGTCAGCTC,AGTCAGCTCG等。在这些表示法中,字典序最小的称 为”最小表示”。 
 
输入一个长度为n(n≤100)的环状DNA串(只包含A、C、G、T这4种字符)的一种表示法,你的任务是输出该环状串的最小表示。例如,CTCC的最小表示是 CCCT,CGAGTCAGCT的最小表示为AGCTCGAGTC。

#include<stdio.h>
#include<string.h>
#define maxn 105
//环状串s的表示法p是否比表示法q的字典序小
int less(const char *s,int p, int q)
{int n=strlen(s);for(int i=0;i<n;i++){if(s[(p+i)%n]!=s[(q+i)%n])return s[(p+i)%n]<s[(q+i)%n];}return 0;//相等
}
int main()
{  int T;char s[maxn];scanf("%d",&T);  //可循环输入的次数 while(T--){scanf("%s",s);   //环状串 int ans=0;int n=strlen(s);for(int i=1;i<n;i++) if(less(s,i,ans)) ans=i;for(int i=0;i<n;i++)putchar(s[(i+ans)%n]);putchar('\n');} return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33

字典序

所谓字典序,就是字符串在字典中的顺序。一般地, 对于两个字符串,从第一个字符开始比较,当某一个位置的字符不同时,该位置字符较小的串,字典序较小(例如,abc比bcd小);如果其中一个字符串已经没有更多字符,但另一个字符串还没结束,则较短的字符串的字典序较小(例如,hi比history小)。字典序的概念可以推广到任意序列,例如,序列1, 2, 4, 7比1, 2, 5小。

3.4注解与习题

习题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。

#include<stdio.h>
#include<string.h>
char s[81];
int main()
{     scanf("%s", s);  int countO = 0;  for(int i = 0; i < strlen(s); i++) {if(s[i] == 'X') {printf("0");countO=0;   }else{printf("%d",++countO);}if(i!=strlen(s)-1)printf("+");}   return 0;
} 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

习题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。

输入:
4
C
C6H5OH
NH2CH2COOH
C12H22O11输出:
12.010
94.108
75.070
342.296
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
#include<stdio.h>
#include<ctype.h>
#define maxn 85
const double d[] = {0,0,12.01,0,0,0,0,1.008,0,0,0,0,0,14.01,16.00};
char s[maxn];
int main()
{  int t;    scanf("%d", &t); while(t--){double sum=0;int i,n;scanf("%s",s);char x=s[0];for(i=0;s[i]!='\0';++i){if(isalpha(s[i]))  //如果是字母 {x=s[i];//将s中的字母赋值给xsum+=d[x-'A'];//sum加上d[]中对应位置上的原子量 }else  //如果是数字 {n=s[i]-'0';//将数字赋值给nwhile(isdigit(s[i+1]))  //s下一个也是数字 {n=n*10+(s[i+1]-'0');i++; } //一直到不是数字位置 sum+=d[x-'A']*(n-1);//x在if已经被赋值,-1是因为if里加了一个 } }printf("%.3f\n",sum); } return 0;
} 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38

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

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

#include<stdio.h>
#include<string.h>
#define maxn 85
char s[maxn];
int main()
{ int a[10]={0,0,0,0,0,0,0,0,0,0};      scanf("%s", s); for(int i=0;i<strlen(s);i++){switch(s[i]) {case '0':   a[0]++;break;case '1':   a[1]++;break;case '2':   a[2]++;break;case '3':   a[3]++;break;case '4':   a[4]++;break;case '5':   a[5]++;break;case '6':   a[6]++;break;case '7':   a[7]++;break;case '8':   a[8]++;break;case '9':   a[9]++;break;default:    break;}}for(int i=0;i<10;i++)printf("%d\n",a[i]);return 0;
} 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29

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

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

输入:
3
haha
hellohellohello
hehehihehehihehehi输出:
2
5
6
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
#include<stdio.h>
#include<string.h>
#define maxn 85
char s[maxn];
int main()
{ int n;scanf("%d",&n);while(n--){scanf("%s",s);  int l=strlen(s);int k,i;for(int i=1;i<l;i++){if(l%i==0)  //l可以被i整除 {for(k=i;k<l;k++){if(s[k]!=s[k%i])//注意算法!后k个位置上的字母都与k%i(就是前i个字母)比较break;}if(k==l){printf("%d\n",i);break;//最小的周期 }}}if(n)   printf("\n"); }return 0;
} 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33

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

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

输入:
TRGSJ
XDOKI
M_VLN
WPABE
UQHCF ARRBBL0 ABCDE
FGHIJ
KLMNO
PQRS_
TUVWX AAA
LLLL0 ABCDE
FGHIJ
KLMNO
PQRS_
TUVWX AAAAABBRRRLL0
Z输出:
Puzzle #1:
T R G S J
X O K L I
M D V B N
W P _ A E
U Q H C FPuzzle #2:
_ A B C D
F G H I E
K L M N J
P Q R S O
T U V W XPuzzle #3:
This puzzle has no final configuration.
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
#include<stdio.h>
#include<string.h>
#include <cctype>
#define maxn 5const int dir[4][2] = {{-1, 0}, {1, 0}, {0, 1}, {0, -1}};
const char s[] = "ABRL";
char a[maxn][maxn];int main() {int t = 0;while(gets(a[0])) {//注意读的是第一行!//读入if(a[0][0] == 'Z') break;//判断的是第一个字母if (t) {puts("");}int m = 0, n = 0;  //记录标记字符位置 for(int i = 0; i < maxn; i++) {if (i) {//不是第一行gets(a[i]);}for(int j = 0; j < maxn; j++) {if(a[i][j]  == '_' || a[i][j] == 0) {//注意 前四个位置是否有空,或第五个位置(字符串尾)为空不显示!且若||前面的成立不读后面的!a[i][j] = '_';m = i; n = j;//将空的位置记下来}}}//移动bool ok = true;  //判断是否移动了for (;;) {char c = getchar();if (c == '0') {break;}bool q = isspace(c);//isspace(c):检查参数c是否为空白字符,是为真,否为假for (int i = 0; i < 4 && ok; i++) {if (c == s[i]) {//c为R,L,A,B中的一个q = true;int x = m + dir[i][0], y = n + dir[i][1];//将新的位置算出(方法巧不用写那么多)if (x < 0 || x > 4 || y < 0 || y > 4) {ok = false;break;}a[m][n] = a[x][y];//将移动位置上的字母给空的位置a[x][y] = '_';//将新位置为空m = x, n = y;//重新记新的位置}}if (!q) {// q 是为了判断是否是空白字符的时候ok = false;}}//输出printf("Puzzle #%d:\n", ++t);if (ok) {for(int i = 0; i <= 4; ++i) {for(int j = 0; j <= 4; ++j) {if (j) {printf(" ");//输空格用的,最后字母后没空格}printf("%c", a[i][j]);}printf("\n");}}else {printf("This puzzle has no final configuration.\n");}}return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89

C语言 gets()和scanf()函数的区别

scanf( )函数和gets( )函数都可用于输入字符串,但在功能上有区别。若想从键盘上输入字符串”hi hello”,则应该使用gets函数。 
gets可以接收空格;而scanf遇到空格、回车和Tab键都会认为输入结束,所有它不能接收空格。 
char string[15]; gets(string); /遇到回车认为输入结束/ 
scanf("%s",string); /遇到空格认为输入结束/ 
所以在输入的字符串中包含空格时,应该使用gets输入。 
在C语言中,能构获取字符串的函数至少有两个: 
1.scanf() 
所在头文件:stdio.h 
语法:scanf(“格式控制字符串”,变量地址列表); 
接受字符串时:scanf(“%s”,字符数组名或指针); 
2.gets() 
所在头文件:stdio.h 
语法:gets(字符数组名或指针); 
两者在接受字符串时: 
1.不同点: 
scanf不能接受空格、制表符Tab、回车等; 
而gets能够接受空格、制表符Tab和回车等; 
2.相同点: 
字符串接受结束后自动加’\0’。 
例1:

#include <stdio.h>
main()
{char ch1[10],ch2[10];scanf("%s",ch1);gets(ch2);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

依次键入asd空格fg回车,asd空格fg回车,则ch1=”asd\0”,ch2=”asd fg\0”。

例2:

#include <stdio.h>
main()
{char ch1[10],ch2[10],c1,c2;scanf("%s",ch1);c1=getchar();gets(ch2);c2=getchar();
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

依次键入asdfg回车,asdfg回车,则ch1=”asdfg\0”,c1=’\n’,ch2=”asdfg\0”,c2需输入。

scanf :当遇到回车,空格和tab键会自动在字符串后面添加'\0',但是回车,空格和tab键仍会留在输入的缓冲区中。
gets:可接受回车键之前输入的所有字符,并用'\n'替代 '\0',回车键不会留在输入缓冲区中。
gets()用到读取字符串,用回车结束输入。
scanf()可以读取所有类型的变量。
  • 1
  • 2
  • 3
  • 4

C语言puts()函数:将一个字符串放入标准输出流(stdout)中

头文件:#include<stdio.h> 
puts()函数用于将一字符串放到标准输出流(stdout)中,并在最后增加换行符 ‘\n’,其函数原型如下: 
int puts(char *string); 
【参数】string为要输出的字符串。 
【返回值】输出成功返回非0值,否则返回0。 
puts()从string的开头往stdout中输出字符,直到遇见结束标志 ‘\0’,’\0’不会被输出到stdout。

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

输入一个r行c列(1≤r,c≤10)的网格,黑格用“*”表示,每个白格都填有一个字母。如果一个白格的左边相邻位置或者上边相邻位置没有白格(可能是黑格,也可能出了网格边界),则称这个白格是一个起始格。 
首先把所有起始格按照从上到下、从左到右的顺序编号为1, 2, 3,…,如图3-7所示。 
 
接下来要找出所有横向单词(Across)。这些单词必须从一个起始格开始,向右延伸到 一个黑格的左边或者整个网格的最右列。最后找出所有竖向单词(Down)。这些单词必须从一个起始格开始,向下延伸到一个黑格的上边或者整个网格的最下行。

Sample Input
2 2
AT
*O
6 7
AIM*DEN
*ME*ONE
UPON*TO
SO*ERIN
*SA*OR*
IES*DEA
0
Sample Output
puzzle #1:
Across1.AT3.O
Down1.A2.TOpuzzle #2:
Across1.AIM4.DEN7.ME8.ONE9.UPON11.TO12.SO13.ERIN15.SA17.OR18.IES19.DEA
Down1.A2.IMPOSE3.MEO4.DO5.ENTIRE6.NEON9.US10.NE14.ROD16.AS18.I20.A

算法竞赛入门经典第3章相关推荐

  1. 《算法竞赛入门经典》第一章1.5

    1.5.4 问题1 问题2 问题3 问题4 问题5  最邻近的else 转载于:https://www.cnblogs.com/LzKlyhPorter/p/4185828.html

  2. 算法竞赛入门经典 第七章 总结

    目录: 7.1 简单枚举 7.2 枚举排列 7.3 子集生成 7.1 简单枚举 例题7-1 除法(Division, UVa 725) 输入正整数n,按从小到大的顺序输出所有形如abcde/fghij ...

  3. 算法竞赛入门经典 第五章总结1

    例题1: 输入多行数据,每行包含若干个以空格隔开的整数,输出每行中所有整数之和 #include<iostream> #include<string> #include< ...

  4. 算法竞赛入门经典第六章(例题) B - Rails(涉及到栈的运用)

    题目:B - Rails 原题链接:https://cn.vjudge.net/contest...: 题目大意:先输入一个表示火车的节数,火车原本是按从1到n的顺序,但是一起进的还是分开进的是不一定 ...

  5. 《算法竞赛入门经典》 第二章 循环结构程序设计 习题

    注:这里为了便于测试,直接使用stdin,stdout进行输出,没有进行文件读写操作. 习题2-1 位数(digit) 输入一个不超过10^9的正整数,输出它的位数.例如12735的位数是5.请不要使 ...

  6. 刘汝佳算法竞赛入门经典第三章习题

    /*给出一些容易理解的解题方法  但是没有oj评测 所以无法保证一定正确  矩阵的旋转给出了左旋和右旋 不确定题目3-5是哪一种*/ 习题3-1分数统计(stat) 输入一些学生的分数,哪个分数出现的 ...

  7. 《算法竞赛入门经典》第一章习题答案

    习题1-1 平均数(average) 输入3个整数,输出它们的平均值,保留3位小数. #include <stdio.h> int main() { int a,b,c; scanf(&q ...

  8. 算法竞赛入门经典第4章 【uvaoj习题(一)】

    题目合集 http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=94 uva100 ...

  9. 算法竞赛入门经典(第二版)第三章习题

    声明:作者水平有限,只是会基础C语言的小菜,C++还未入门.作者仅根据算法竞赛入门经典(第二版)书上第三章习题所述题意而编写,并未严格按照原题的输入输出编写,代码仅经过个人测试(OJ网站太慢了).代码 ...

最新文章

  1. MyEclipse断点调试
  2. php peridot 使用教程,PHP测试框架Peridot-支持BDD
  3. html 文字倒映效果,HTML图片CSS滤镜—倒影效果
  4. ScottGu之博客翻译-LINQ to SQL第三部分,查询数据库 (Part 3 - Querying our Database)
  5. 数据挖掘基础知识-矩阵(分解)
  6. linux磁盘符变化autofs,Linux基础教程学习笔记之Autofs自动挂载
  7. python学习之数据类型(int,bool,str)
  8. c语言随机产生四位数,习题:随机产生N个四位正整数,将其中的素数选出,并升序排列之输…...
  9. 32bit win7 在VMWARE中安装64位的redhat LINUX4.7
  10. Npm 恶意包试图窃取 Discord 敏感信息和浏览器文件
  11. Bailian2758 菲波那契数列(2)【递推】
  12. ANSYS 2020R2 workbench汉化的方法
  13. 【ENVI】基于Landsat遥感影像的盐城市土地利用信息提取
  14. 电脑版微信多开的方法
  15. 七大黄金定律与产品设计
  16. 工厂模式C++实现(三种工厂模式附详细注释)
  17. CVPR2022 Oral:StreamYOLO-流感知实时检测器
  18. 虚拟机中的Linux系统如何联网?
  19. 为什么选独立服务器?
  20. 金蝶应收应付模块流程_金蝶应收应付手册

热门文章

  1. Perfmon-Windows 自带检测工具(性能测试)
  2. java jna java.lang.UnsatisfiedLinkError: Unable to load library Native library (win32-x86-64/C:\User
  3. 奥德赛修改器_语音奥德赛2020的声音在演讲者嵌入方面取得了进步
  4. php 风水起名网站源代码_开运网付费开源商业版 PHP风水起名八字算命易经周易源码...
  5. 如何设置电脑点击链接后打开的网页为自己想用的浏览器
  6. 新形势下幼儿园班级管理模式初探
  7. 上海普陀区学计算机学校哪里有,2021年上海普陀民办学校电脑随机录取结果的公示...
  8. 手机接收到的Excel文件如何转换成PDF文档
  9. 红米note+html编辑器,红米Note7 Pro使用LineageOS 16问题备忘录
  10. 关于U3D的最新版本的更新问题