演算法競賽入門經典第3章習題
阿新 • • 發佈:2018-12-28
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;
}