太久沒(méi)有做 zoj,對(duì) oj 來(lái)說(shuō),由于它高度的”黑盒性“(輸入數(shù)據(jù)和答案完全保密),保護(hù)自信心是非常重要的。所以我先選擇一道非常簡(jiǎn)單的題目刷起。本題目是一個(gè)相當(dāng)簡(jiǎn)單的題目,難度系數(shù)和求 A+B 相當(dāng)。
本題,已知一個(gè)指針,初始狀態(tài)指向 N(北),現(xiàn)在對(duì)指針做一系列順時(shí)針(C)或者逆時(shí)針(A)旋轉(zhuǎn) 90 度的操作,問(wèn)指針然后指向哪個(gè)方向。
由于四個(gè)方向形成一個(gè)循環(huán),所以很自然的提示出,把四個(gè)方向所在的”圓環(huán)“展開成一個(gè)數(shù)組,所有的旋轉(zhuǎn)操作實(shí)際上是移動(dòng)數(shù)組內(nèi)的索引,對(duì)索引進(jìn)行遞增或者遞減的操作。然后對(duì)索引進(jìn)行對(duì)數(shù)組長(zhǎng)度的 MOD (取余)操作,限制在合理范圍內(nèi)即可。
設(shè)索引值為 x,初始值為 0,定義向逆時(shí)針?lè)较蛐D(zhuǎn)定義為正方向,則:
逆時(shí)針(A)旋轉(zhuǎn) 90 度:x = ( x + 1 ) % 4;
順時(shí)針(C)選擇 90 度:x = ( x - 1 + 4 ) % 4 = ( x + 3 ) % 4;
因此,我們需要把旋轉(zhuǎn)方向(A 或 C),映射到對(duì) x 的遞增值(1 或 3 )上。因此我們發(fā)現(xiàn)這里有一個(gè)巧合:A 和 C 之間的差值(C - A = 2),恰好也是這個(gè)遞增值之間的差值( 3 - 1 = 2)。所以這個(gè)映射關(guān)系,不需要使用條件判斷,可以直接寫出此映射關(guān)系:
x = ( x + *p - 'A' + 1 ) % 4; ( *p = 'A' 或 'C' )
如果我們進(jìn)一步查閱一下 ASCII 碼表,上面的代碼也等效于:
x = ( x + *p - '@' ) % 4; 或者 x = ( x + *p - 0x40 ) % 4;
最終代碼如下:
#include <stdio.h> int main(int argc, char* argv[]) { int i, x, count = 0; char *p; char directions[8] = "NWSE"; char line[128]; scanf("%d\n", &count); for(i = 0; i < count; i++) { gets(line); p = line; x = 0; while(*p) { x = (x + (*p - 'A' + 1)) & 3; ++p; } printf("%c\n", directions[x]); } return 0; }
【補(bǔ)充】由于旋轉(zhuǎn)次數(shù)很少(不超過(guò) 100 次),因此如果我們一直對(duì) x 進(jìn)行累加,也不會(huì)溢出 int 的最大值。所以在 while 循環(huán)中的 MOD 操作可以去除,僅在最后輸出結(jié)果時(shí),對(duì) x 進(jìn)行一次 MOD 操作即可。
浙公網(wǎng)安備 33010602011771號(hào)