題目出自DS課本第二章,滿有意思的一題。
題目
一隻喝醉酒的小強在地板上爬來爬去,
假設地板面積為row * col。
假設小強的起始位置為座標(i, j),
小強一次可以移動一格。
小強可以從他現在所待的格子,
移動到周遭其他格子,且機率相等。
請問小強爬過每塊面積至少一次,
需要花多久時間?
輸出總步數與每塊格子經過的次數。
分析
算是一題模擬題。
首先要知道地板的大小,
意即maxrow跟maxcol要定出來。
接著要知道起始點row, col。
從起始點開始往周遭移動,
我們還需要隨機函式與移動方式。
小強從自身待的格子移動到周遭至多有八格。
(八格就是八種情況)
需要考慮邊界問題,與上界問題。
邊界表示,小強移動只能在地板中,不能移動到地板之外;
上界表示,一個格子至多經過x次,超過x次就不能再進入格子。
(這個動作確保有解,程式才得以終止。)
課本提供一種很好的移動資料結構:利用陣列。
假設移動的row座標為mover,
移動的col座標為movec。
小強可以移動到左上,上,右上,右,右下,下,左下,左。
看出來了嗎!
一個點對應一組mover跟movec。
所以mover與movec的內容分別是:
mover[8] = {1, 1, 1, 0, -1, -1, -1, 0};
movec[8] = {-1, 0, 1, 1, 1, 0, -1, -1};
至於要怎麼移動呢?
row = i + mover[j]
col = j + movec[j]
j從0到7為止。
如此配合隨機函式,可以隨機得到一個數字,
介於0到7,得到row與col後,再考慮邊界問題,
若在編界之內,且經過該格子的次數小於x就移動到(row, col)。
到小強每塊格子都經過至少一次時,
就可以輸出總步數與格子的經過情況數。
如果可以用顏色深淺代表移動次數那一定更好玩 XD。
實做程式碼
/* DS ch 2.9 exercise 9
* mythnc
* 2011/11/29 10:56:04
*/
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define ROW 40
#define COL 20
#define FALSE 0
#define TRUE 1
#define MAXT 50000
typedef struct point {
int x;
int y;
} Point;
void move(Point, int (*)[], int, int);
int terminal(int (*)[], int, int);
void printout(int (*)[], int, int);
int totalmove = 1;
int main(void)
{
int square[ROW][COL] = { 0 };
int maxrow, maxcol;
Point start;
printf("max row and col: ");
scanf("%d %d", &maxrow, &maxcol);
getchar();
printf("start point (x, y): ");
scanf("%d %d", &start.x, &start.y);
getchar();
move(start, square, maxrow, maxcol);
system("clear");
printout(square, maxrow, maxcol);
return 0;
}
/* move: cockroach move simulation */
void move(Point start, int (*s)[COL], int maxr, int maxc)
{
int xmove[] = {1, 1, 1, 0, -1, -1, -1, 0};
int ymove[] = {-1, 0, 1, 1, 1, 0, -1, -1};
int i, x, y;
srand((unsigned)time(NULL));
s[start.x][start.y]++;
while (!terminal(s, maxr, maxc)) {
system("clear");
printout(s, maxr, maxc);
getchar();
i = rand() % 8;
x = start.x + xmove[i];
y = start.y + ymove[i];
if (x >= 0 && x < maxr && y >= 0 && y < maxc
&& s[x][y] <= MAXT) {
s[x][y]++;
totalmove++;
start.x = x;
start.y = y;
}
}
}
/* terminal: terminal contidion */
int terminal(int (*s)[COL], int maxr, int maxc)
{
int i, j;
for (i = 0; i < maxr; i++)
for (j = 0; j < maxc; j++)
if (s[i][j] == 0)
return FALSE;
return TRUE;
}
/* printout: print out result */
void printout(int (*s)[COL], int maxr, int maxc)
{
int i, j;
printf("\ntotal move: %d\n", totalmove);
printf("count array:\n\n");
for (i = 0; i < maxr; i++) {
printf("%5d", s[i][0]);
for (j = 1; j < maxc; j++)
printf(" %5d", s[i][j]);
putchar('\n');
}
putchar('\n');
}