題解 P6369 [COCI2006-2007#6] MARATON
阿新 • • 發佈:2020-10-14
蒟蒻題解首祭!!!
咕了三星期了
先分析下題意:
一個由各個字母與 ‘.’ 組成的正方形矩陣(邊長小於等於30)
求任意行列斜線上有沒有3個連續相同的字母。
就這,無了。
思考下演算法
資料範圍很小(只有30),我們為什麼不用最無腦的遍歷列舉呢?
輸入就不用多說了,一個字元型陣列,但要注意宣告時,冗餘要稍多一些,防止訪問越界。
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
cin>>MAP[i][j];
遍歷判斷:
某玩家若勝利則此玩家字母連線必定為以下四情況之一
設遍歷到的這個位置座標為(x,y)
類 型 | 座標1 | 座標2 | 座標3 |
---|---|---|---|
行 | (x-1,y) | (x,y) | (x+1,y) |
列 | (x,y+1) | (x,y) | (x,y-1) |
斜線 | (x-1,y+1) | (x,y) | (x+1,y-1) |
斜線 | (x+1,y-1) | (x,y) | (x-1,y+1) |
判斷函式:
void JUDGE(int x,int y) { if((MAP[x-1][y]==MAP[x][y])&&(MAP[x+1][y]==MAP[x][y])) OUT(MAP[x][y]); if((MAP[x][y-1]==MAP[x][y])&&(MAP[x][y+1]==MAP[x][y])) OUT(MAP[x][y]); if((MAP[x-1][y-1]==MAP[x][y])&&(MAP[x+1][y+1]==MAP[x][y])) OUT(MAP[x][y]); if((MAP[x+1][y-1]==MAP[x][y])&&(MAP[x-1][y+1]==MAP[x][y])) OUT(MAP[x][y]); }
這個時候陣列冗餘就發揮作用了,可以略去越界判斷只需要輸出時進行一次特判就可以。
輸出函式:
void OUT(char c)
{
if(c!='.'&&c!=0)
{
printf("%c",c);
sign=false;
}
}
此外,我們還需要一個sign變數(bool)記錄是否有贏家,以此判斷是否輸出"ongoing"
if(sign)
printf("ongoing");
完整程式碼(20ms,660.00KB):
#include<bits/stdc++.h> using namespace std; int n; char MAP[35][35]; bool sign=true;//記錄是否有贏家 void JUDGE(int,int),OUT(char); int main() { memset(MAP,0,sizeof(MAP)); scanf("%d",&n); for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) cin>>MAP[i][j]; for(int i=1;i<=n&&sign;i++)//迴圈必須判斷sign情況 不然可能重複輸出 for(int j=1;j<=n&&sign;j++) JUDGE(i,j); if(sign)//若遍歷後無贏家輸出"ongoing" printf("ongoing"); return 0; } void JUDGE(int x,int y) { if((MAP[x-1][y]==MAP[x][y])&&(MAP[x+1][y]==MAP[x][y])) OUT(MAP[x][y]);//行 if((MAP[x][y-1]==MAP[x][y])&&(MAP[x][y+1]==MAP[x][y])) OUT(MAP[x][y]);//列 if((MAP[x-1][y-1]==MAP[x][y])&&(MAP[x+1][y+1]==MAP[x][y])) OUT(MAP[x][y]);//斜線 if((MAP[x+1][y-1]==MAP[x][y])&&(MAP[x-1][y+1]==MAP[x][y])) OUT(MAP[x][y]);//斜線 } void OUT(char c) { if(c!='.')//棋盤中可能有連續3個'.'構成的線 { printf("%c",c); sign=false;//更新sign } }
完結撒fa~