【【類比題】】
【題目】 The Worm Turns Time Limit: 2 Seconds Memory Limit: 65536 KB
Worm is an old computer game. There are many versions, but all involve maneuvering a "worm" around the screen, trying to avoid running the worm into itself or an obstacle.
We'll simulate a very simplified version here. The game will be played on a 50 x 50 board, numbered so that the square at the upper left is numbered (1, 1). The worm is initially a string of 20 connected squares. Connected squares are adjacent horizontally or vertically. The worm starts stretched out horizontally in positions (25, 11) through (25, 30), with the head of the worm at (25, 30). The worm can move either East (E), West (W), North (N) or South (S), but will never move back on itself. So, in the initial position, a W move is not possible. Thus the only two squares occupied by the worm that change in any move are its head and tail. Note that the head of the worm can move to the square just vacated by the worm's tail.
You will be given a series of moves and will simulate the moves until either the worm runs into itself, the worm runs off the board, or the worm successfully negotiates its list of moves. In the first two cases you should ignore the remaining moves in the list.
Input
There will be multiple problems instances. The input for each problem instance will be on two lines. The first line is an integer n (<100) indicating the number of moves to follow. (A value of n = 0 indicates end of input.) The next line contains n characters (either E, W, N or S), with no spaces separating the letters, indicating the sequence of moves.
Output
Generate one line of output for each problem instance. The output line should be one of the follow three:
The worm ran into itself on move m.
The worm ran off the board on move m.
The worm successfully made all m moves.
Where m is for you to determine and the first move is move 1.
Sample Input
18
NWWWWWWWWWWSESSSWS
20
SSSWWNENNNNNWWWWSSSS
30
EEEEEEEEEEEEEEEEEEEEEEEEEEEEEE
13
SWWWWWWWWWNEE
0
Sample Output
The worm successfully made all 18 moves.
The worm ran into itself on move 9.
The worm ran off the board on move 21.
The worm successfully made all 13 moves.
Source: East Central North America 2001, Practice
【題意說明】
蠕蟲遊戲是比較經典的掌機遊戲,簡單的版本是對於一條在格子介面裡亂竄的蠕蟲,玩家要控制它的移動方向以免它碰到自己的身體或牆壁。題目類比了簡單的蠕蟲遊戲給出一個50×50的格子矩陣,以及其中長度為20個格子的蠕蟲頭、尾座標,初始時蟲身為蟲頭、尾直連。要求根據輸入的運動方向步驟字串('E''W''S''N'表示分別向東西南北移動),輸出蠕蟲的移動結果(某一步蟲頭碰到了自己的身體或者牆壁,或者安全地移動完了所有步驟)。
圖1
【解答】
(一)分析:制定50×50二維BOOL數組bord代表蠕蟲爬動的格子矩陣,數組元素bord(i,j)表示矩陣中橫座標為j、縱座標為i的格子(i增加表示縱座標往上,j增加表示橫座標往右),格子值為true表示該格子為蠕蟲身體,為false表示為空白格,bord(0,0)為矩陣座標系原點。對於每一次移動,格子矩陣中只有2個格子的狀態會發生變化,一個是蟲頭將要移至的格子狀態將要變為true,一個是蟲尾移走後原先所處的格子狀態變為false,故程式設計的類比過程只需考慮蟲頭和蟲尾的移動方向變化,即每次移動步驟根據移動方向確定蟲頭、蟲尾哪一方向面的格子狀態需要變化。需要注意的是,蟲頭牽引著整個蟲身(包括蟲尾)的移動,所以每次蟲頭的方向和輸入給出的每次移動方向相同,而蟲尾的移動方向則要根據當前所處的位置判定,如圖1某輪的移動要求突然向南,則蟲頭向南,而蟲尾原先向東,此時它的東面還有蟲身在移動,故蟲尾仍向東直到其跟隨蟲身移動到南北走向後則向北移動。最終即判定在移動過程中蟲頭將要移至的格子是否為蟲身或越界,否則表示安全移動完成所有輸入步驟要求。
(二)代碼:
#include<iostream>using namespace std;int main(){bool board[50][50];//類比蠕蟲爬行矩陣格子,格子值為true表示該格為蠕蟲身體,false為空白格int hi,hj,ti,tj;//蠕蟲頭格子座標(hi,hj)、尾格子座標(ti,tj)int n;//移動方向串長int i,j;char moves[100],td;//moves表示移動方向串。td表示蟲尾的運動方向while(cin>>n){if(n==0)break;cin>>moves; hi=24;hj=29;ti=24;tj=10;for(i=0;i<50;i++)for(j=0;j<50;j++)board[i][j]=false;for(j=10;j<=29;j++)board[24][j]=true;td='E';for(i=0;i<n;i++){//蟲尾準備移走,騰空原先所處格子board[ti][tj]=false;//移動蟲頭方向if(moves[i]=='E'){hj++;}else if(moves[i]=='W'){hj--;}else if(moves[i]=='N'){hi++;}else{hi--;}//蟲尾隨著蟲頭準備向東,而蟲尾的東面是空格,則蟲尾向南或向北if(td=='E'&&board[ti][tj+1]==false){if(board[ti-1][tj]==true)//蟲尾南面是蟲身,則蟲尾向南{ti--;td='S';}else if(board[ti+1][tj]==true)//蟲尾北面是蟲身,則蟲尾向北{ti++;td='N';}}//蟲尾隨著蟲頭準備向西,而蟲尾的西面是空格,則蟲尾向南或向北else if(td=='W'&&board[ti][tj-1]==false){if(board[ti-1][tj]==true)//蟲尾南面是蟲身,則蟲尾向南{ti--;td='S';}else if(board[ti+1][tj]==true)//蟲尾北面是蟲身,則蟲尾向北{ti++;td='N';}}//蟲尾隨著蟲頭準備向北,而蟲尾的北面是空格,則蟲尾向西或向東else if(td=='N'&&board[ti+1][tj]==false){if(board[ti][tj-1]==true)//蟲尾西面是蟲身,則蟲尾向西{tj--;td='W';}else if(board[ti][tj+1]==true)//蟲尾東面是蟲身,則蟲尾向東{tj++;td='E';}}//蟲尾隨著蟲頭準備向南,而蟲尾的南面是空格,則蟲尾向西或向東else if(td=='S'&&board[ti-1][tj]==false){if(board[ti][tj-1]==true)//蟲尾西面是蟲身,則蟲尾向西{tj--;td='W';}else if(board[ti][tj+1]==true)//蟲尾東面是蟲身,則蟲尾向東{tj++;td='E';}}//蟲尾隨著蟲頭準備向東西南北,而蟲尾的相應東西南北面是蟲身,則蟲尾和蟲頭移動方向相同else{if(td=='E') tj++;else if(td=='W') tj--;else if(td=='S') ti--;else ti++;}//蟲頭碰撞到蟲身if(board[hi][hj]==true){cout<<"The worm ran into itself on move "<<i+1<<"."<<endl;break;}//蟲頭移動到矩陣外界if(hi<0||hi>=50||hj<0||hj>=50){cout<<"The worm ran off the board on move "<<i+1<<"."<<endl;break;}//蟲頭移動到下一個空格board[hi][hj]=true;}if(i>=n)cout<<"The worm successfully made all "<<i<<" moves."<<endl;}return 0;}//Accepted
(解於2009/10)