WERTYU;回文词;猜数字;生成元;环状序列

WERTYU(UVa 10082)常量数组

问题

把手放在键盘上时,稍不注意就会往右错一位。这样,输入Q会变成输入W,输入J会变成输入K等。       

输入一个错位后敲出的字符串(所有字母均大写),输出打字员本来想打出的句子。输入保证合法,即一定是错位之后的字符串。例如输入中不会出现大写字母A。

样例输入

O S, GOMR YPFSU/

样例输出

I AM FINE TODAY.

分析

每输入一个字符,都可以直接输出一个字符,因此getchar是输入的理想方法。问题在于:如何进行这样输入输出变换呢?一个较好的方法是使用常量数组。

代码

#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;
}

常量数组s中的 \\ 是转义字符。用 \\ 这个字符来表示真正意义上的反斜线即 \ 。

回文词(Palindromes,UVa401)字符函数+常量数组

问题

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

 输入的每行包含一个字符串(保证只有上述字符。不含空白字符),判断它是否是回文串和镜像串(共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. 

#include<iostream>
#include<string.h>
#include<ctype.h>
using namespace std;
const char* rev = "A   3  HIL JM O   2TUVWXY51SE Z  8 "; //指针名可直接当数组名使用,均指代地址
const char* msg[] = { "not a palindrome","a regular palindrome",  //二维数组,msg前面要加*
                    "a mirrored string","a mirrored palindrome" };
//四种组合:既不是回文也不是镜像、只是回文、只是镜像、既是回文又是镜像

char mirror(char ch) {  //求字母或数字的镜像
    if (isalpha(ch)) return rev[ch - 'A'];
    return rev[ch - '0' + 25];
}

int main() {
    char s[30];
    while (cin >> s) {
        int len = strlen(s);
        int m = 1, p = 1;
        for (int i = 0; i <= (len / 2); i++) {
            if (s[i] != s[len - 1 - i]) p = 0;//不是回文串
            if (mirror(s[i]) != s[len - 1 - i]) m = 0;//不是镜像串
        }
        cout << s << " -- is " << msg[m * 2 + p] << '.' << endl << endl;
    }
    return 0;
}

本题用isalpha来判断字符是否为字母,类似的还有isdigit、isprint等,在ctype.h中定义。由于ASCII码表中大写字母、小写字母和数字都是连续的,如果ch是大写字母,则ch-'A'就是它在字母表中的序号(A的序号是1,B的序号是2,依此类推);类似地,如果ch是数字,则ch-'0'就是这个数字的数值本身(‘5’-‘0’=5)。

ctype.h中定义的isalpha、isdigit、isprint等工具可以用来判断字符的属性,而toupper、tolower等工具可以用来转换大小写。

猜数字游戏的提示(Master-Mind Hints,UVa340)数组统计

实现一个经典的“猜数字”游戏。给定答案序列和用户猜的序列,统计有多少数字位置正确(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)

分析

直接统计可得A,为了求B,对于每个数字(1-9),统计二者出现的次数c1和c2,则min(c1,c2)就是该数字对于B的贡献。最后减去A的部分。

#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时输入结束
		printf("Game %d:\n", ++kase);
		for(int i = 0; i < n; i++) scanf("%d", &a[i]);
		for(;;){
			int A = 0, B = 0;
			for(int i = 0; i < n; i++){
				scanf("%d", &b[i]);
				if(a[i] == b[i]) A++; 
			}
			if(b[0] == 0) break;//正常的猜测序列不会有0,所以只判断第一个数是否为0即可
			for(int d = 1; d <= 9; d++){
				int c1 = 0, c2 = 0;//统计数字d在答案序列和猜测序列中各出现多少次
				for(int i = 0; i < n; i++){
					if(d == a[i]) c1++;
					if(d == b[i]) c2++;
				}
				if(c1 < c2) B+= c1; else B+= c2;
			}
			printf("    (%d,%d)\n", A, B-A);
		}	
	}
	return 0;
}

生成元(Digit Generator, UVa1583)预处理+查表

如果x加上x的各个数字之和得到y,就说x是y的生成元。

给出n(1≤n≤100000),求最小 生成元。无解输出0。例如,n=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; x /= 10; }
    if(ans[y] == 0 || m < ans[y]) ans[y] = m;
  }
  scanf("%d", &T);
  while(T--) {
    scanf("%d", &n);
    printf("%d\n", ans[n]);
  }
  return 0;
}

环状序列(Circular Sequence, UVa1584)字典序

长度为n的环状串有n种表示法,分别为从某个位置开始顺时针得到。例如,图3-4的环状串有10种表示:CGAGTCAGCT,GAGTCAGCTC,AGTCAGCTCG等。在这些表示法中,字典序最小的称为”最小表示”。

输入一个长度为n(n≤100)的环状DNA串(只包含A、C、G、T这4种字符)的一种表示法,你的任务是输出该环状串的最小表示。

#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;
}

猜你喜欢

转载自blog.csdn.net/LXQ1071717521/article/details/82840123