问题链接:CCF NOI1057 石头剪刀布。
时间限制:
1000 ms 空间限制: 262144 KB
题目描述
Bart的妹妹Lisa在一个二维矩阵上创造了新的文明。矩阵上每个位置被三种生命形式之一占据:石头,剪刀,布。每天,上下左右相邻的不同生命形式将会发生战斗。在战斗中,石头永远胜剪刀,剪刀永远胜布,布永远胜石头。每一天结束之后,败者的领地将被胜者占领。
你的工作是计算出n天之后矩阵的占据情况。
输入
第一行包含三个正整数r,c,n,分别表示矩阵的行数、列数以及天数。每个整数均不超过100。
接下来r行,每行c个字符,描述矩阵初始时被占据的情况。每个位置上的字符只能是R,S,P三者之一,分别代表石头,剪刀,布。相邻字符之间无空格。
输出
输出n天之后的矩阵占据情况。每个位置上的字符只能是R,S,P三者之一,相邻字符之间无空格。
样例输入
3 3 1
RRR
RSR
RRR
样例输出
RRR
RRR
RRR
问题分析
这是一个模拟题,直接模拟计算即可。
需要用一些程序技巧,使得程序代码简洁一些。
程序说明
上下左右的坐标放在数组around[]中,程序的处理就可以用循环来控制。
定义二维数组用于存储二维矩阵,周围多出一圈,可以省去数组下标的越界判定。
函数doit()封装的功能是计算每一天过后矩阵的占据情况。
- 先定义一个符号常量,再用它来定义二维数组,可以使得程序的通用性得到提高。
- 一些编程技巧有助于简化程序的代码。
- 函数memset()用于给大量的存储空间设置初始值是方便的。
- 数组around[]存储周围元素的相对下标,使得无序变有序,可以用循环来处理。
参考链接:(略)。
100分通过的C语言程序:
#include <stdio.h> #include <string.h> struct _around { int drow; int dcol; } around[] = {{-1, 0}, {0, 1}, {1, 0}, {0, -1}}; #define AN 4 #define N 100 char a[N+2][N+2], b[N+2][N+2]; void doit(char x[][N+2], char y[][N+2], int r, int c) { int i, j, k; for(i=1; i<=r; i++) for(j=1; j<=c; j++) if(x[i][j] == 'R') { for(k=0; k<AN; k++) if(x[i + around[k].drow][j + around[k].dcol] == 'S') y[i + around[k].drow][j + around[k].dcol] = 'R'; } else if(x[i][j] == 'S') { for(k=0; k<AN; k++) if(x[i + around[k].drow][j + around[k].dcol] == 'P') y[i + around[k].drow][j + around[k].dcol] = 'S'; } else if(x[i][j] == 'P') { for(k=0; k<AN; k++) if(x[i + around[k].drow][j + around[k].dcol] == 'R') y[i + around[k].drow][j + around[k].dcol] = 'P'; } } int main(void) { int r, c, n, i, j, k; memset(a, 0, sizeof(a)); scanf("%d%d%d", &r, &c, &n); for(i=1; i<=r; i++) scanf("%s", a[i]+1); memcpy(b, a, sizeof(a)); for(k=1; k<=n; k++) if(k & 1) { doit(a, b, r, c); memcpy(a, b, sizeof(a)); } else { doit(b, a, r, c); memcpy(b, a, sizeof(a)); } for(i=1; i<=r; i++) { for(j=1; j<=c; j++) printf("%c", a[i][j]); printf(" "); } return 0; }