3-1. 得分(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>
#define Maxn 80
char s[Maxn];
int main() {
scanf("%s", s);
int score = 0, tot = 0;
for(int i = 0; i < strlen(s); i++)
{
if(s[i]=='X')
score = 0;
else if(s[i]=='O')
score++;
tot += score;
}
printf("%d\n", tot);
return 0;
}
3-2.分子量(UVa1586)
给出一种物质的分子式(不带括号),求分子量。本题的分子式只包含4种原子,分别为C,H,O,N,原子量为12.01,1.008,16.00,14.01(单位:g/mol)。例如,C6H5OH的分子量为94.108 g/mol。按照题目做就行了。
#include<stdio.h>
#include<string.h>
#define Maxn 80
int main() {
char s[Maxn];
scanf("%s", s);
float tot = 0, score = 0;
int num;
for(int i = 0; i < strlen(s); i++)
{
switch(s[i])
{
case 'C': {score = 12.01; break;}
case 'H': {score = 1.008; break;}
case 'O': {score = 16.00; break;}
case 'N': {score = 14.01; break;}
}
if(s[i+1] > '0' && s[i+1] <= '9')
{
num = s[i+1] - '0';
i++;
}
tot += score * num;
num = 1;
}
printf("%.3f\n", tot);
return 0;
}
3-3 数数字(UVa1225)
把前n(n <= 10000)个整数顺次写在一起:123456789101112...数一数0~9各出现多少次(输出10个整数,分别是0,1,2,..., 9出现的次数)。
#include<stdio.h>
#include<string.h>
#define Maxn 10005
char s[Maxn];
int a[10];
int main() {
scanf("%s", s);
for(int i = 0; i < strlen(s); i++)
a[s[i]-'0'] ++;
for(int i = 0; i < 10; i++)
printf("%d ", a[i]);
printf("\n");
return 0;
}
3-4 周期串 (Uva455)
如果一个字符串可以由某个长度为k的字符串重复多次得到,则称该串以k为周期。例如,abcabcabcabcabc 以3为周期(注意,它也以6 和 12 为周期)。输入一个长度不超过80的字符串,输出其最小周期。解法就是:
从小到大枚举各个周期(即从1到字符串大小),一旦符合条件就立即输出。当不是周期串时输出的最小周期即为其本身长度。
#include<stdio.h>
#include<string.h>
#define maxn 101
char s[maxn];
int main() {
scanf("%s", s);
int i, j, flag = 1; /* i记录周期的长度, j记录第二周期开始的位置*/
int len = strlen(s);
for(i = 1; i <= len; i++)
if(len % i == 0) //字符串的长度肯定可以被周期整除
{
flag = 1;
//检测是否有周期性
for(j = i; j < len; j++)
{
if(s[j] != s[j%i])
{
flag = 0;
break;
}
}
if(flag) //如果是周期,即刻跳出
break;
}
printf("%d", i);
return 0;
}
3-5 谜题(UVa227)
有一个5*5的网络,其中恰好有一个格子是空的,其他格子各有一个字母。一个有4种指令:A, B, L, R, 分别表示把空格上、下、左、右的相邻字母移到空格中。输入初始网格和指令序列(以数字0结束),输出指令执行完毕后的网络。如果有非法指令,应输出" This puzzle has no final configuration."。
T | R | G | S | J |
X | D | O | K | I |
M | V | L | N | |
W | P | A | B | E |
U | Q | H | C | F |
T | R | G | S | J |
X | O | K | L | I |
M | D | V | B | N |
M | P | A | E | |
U | O | H | C | F |
解法:输入初始网格和指令序列,初始网格用二维数组表示,分别按照指令顺序进行将字母 移到空格,遇到0就结束。
#include<stdio.h>
#include<string.h>
#define n 5
char s[n][n];
int main() {
int i, j;
char c;
int i_Null = 0, j_Null = 0;
for(i = 0; i < n; i++)
for(j = 0; j < n; j++)
{
scanf("%c", &s[i][j]);
if(s[i][j] == '*')
{i_Null = i; j_Null = j;}
}
fflush(stdin);
while((c = getchar()) != EOF){
if(c == '0') break;
switch(c)
{
case 'A': {s[i_Null][j_Null] = s[i_Null-1][j_Null]; s[i_Null-1][j_Null] = '*'; i_Null--; break;}
case 'B': {s[i_Null][j_Null] = s[i_Null+1][j_Null]; s[i_Null+1][j_Null] = '*'; i_Null++;break;}
case 'L': {s[i_Null][j_Null] = s[i_Null][j_Null-1]; s[i_Null][j_Null-1] = '*'; j_Null--;break;}
case 'R': {s[i_Null][j_Null] = s[i_Null][j_Null+1]; s[i_Null][j_Null+1] = '*'; j_Null++;break;}
default: {printf("This puzzle has no final configuration."); return 0;}
}
}
printf("\n");
for(i = 0; i < n; i++) {
for(j = 0; j < n; j++)
printf("%c ", s[i][j]);
printf("\n");
}
return 0;
}
3-6 纵横字谜的答案(Uva232)
输入一个r行c列(1<=r, c<=10)的网格,黑格用“*”表示,每个白格都填有一个字母。如果一个白格的左边相邻位置或者上边相邻位置没有白格(可能是黑格,也可能出了网格边界)则称这个白格是一个起始格。首先把所有的起始格按照从上到下的、从左到右的顺序编号为1,2,3,···,如图所示:
1 | 2 | 3 | * | 4 | 5 | 6 |
* | 7 | * | 8 | |||
9 | 10 | * | 11 | |||
12 | * | 13 | 14 | |||
* | 15 | 16 | * | 17 | * | |
18 | * | 19 | 20 |
#include<stdio.h>
#include<string.h>
#define MAX 12
int main(void)
{
char buf[MAX][MAX]; //用来存储字母
int num[MAX][MAX]; //用来存储数字
int r, c;
int count=1, i, j;
while(scanf("%d", &r)&&r!=0)
{
scanf("%d", &c);
memset(num, 0, sizeof(num));
for(i = 0; i < r; i++)
scanf("%s", buf[i]);
int m = 1;
for(i = 0; i < r; i++)
{
for(j = 0; j < c; j++)
{
if(buf[i][j] == '*') //如果这个位置是黑格,不用填
continue;
if((j-1) < 0 || buf[i][j-1] == '*' || (i-1) < 0 || buf[i-1][j] == '*')
{ //这个位置的上面或左面是黑格或是边界,开始往num填数字
num[i][j] = m++;
}
}
}
if(count != 1)
printf("\n");
printf("puzzle #%d:\n", count++);
printf("Across\n");
for(i = 0; i < r; i++)
{
j = 0;
while(j < c)
{
if(num[i][j] == 0 || buf[i][j] == '*')
{//如果这个是黑格或中间无值格,跳过这一次
j++;
continue;
}
printf("%3d.%c", num[i][j], buf[i][j]);//格式需要
j++;
while(j < c && buf[i][j] != '*') //当输出到行结尾时结束或是黑格时
{
printf("%c", buf[i][j]);
j++;
}
printf("\n");
}
}
printf("Down\n");
for(i = 0; i < r; i++)
{
for(j = 0; j < c; j++)
{
if(num[i][j]==0 || buf[i][j]=='*')
continue;
printf("%3d. %c", num[i][j], buf[i][j]);
num[i][j] = 0;
int k = i + 1;
while(k < r && buf[k][j] != '*')
{
printf("%c", buf[k][j]);
num[k][j] = 0;
k++;
}
printf("\n");
}
}
}
return 0;
}
3-7 DNA序列
输入m个长度均为n的DNA序列,求一个DNA序列,到所用序列的总Hamming距离尽量小。两个等长字符串的Hamming距离等于字符不同的位置个数,例如,ACGT和GCGA的Hamming距离为2(左数第1,4个字符不同)。
输入整数m和n(4<=m<=50, 4<=n<=100),以及m个长度为n的DNA序列(只包含字母A,C,G,T),输出到m个序列的Hamming距离和最小的DNA序列和对应的距离。如有多解,要求为字典序最小的结,例如,对于下面5个DNA序列,最优解为TAAGATAC。
TATGATAC
TAAGCTAC
AAAGATCC
TGAGATAC
TAAGATGT