会津大学オンラインジャッジを解くページ。 *問66 Tic Tac Toe http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=0066 チックタックトゥの勝敗判定をする問題。 自分で考えられる限りの短縮を図ったものの平凡なショートコーディングになった。 この問題昔掲示板でヒントはもらって書いたのだけど、今回はその時より短くなっている。 短さ1位の人のコードは想像もつかないがAOJの外には1位の人より上がいるのがネットの世界。 すごいと思う。 AOJばっかりに閉じこもってないで少しは外に出ないとダメか。 コードの短さ6/542位うーん平凡。 #include<stdio.h> int main(){ char *r="0001223613432311",b[10],i,t,p,d; while(scanf("%s",b)>0){ t=i=0; while(i<8){ d=r[i+8]%8; p=r[i++]%8; t|=((b[p]|b[p+d]|b[p+d*2])&18)%3; } printf("%c\n","dxo"[t]); } } *問67 The Number of Island 格子上のデータで海と陸があらわされている島の数を数えよという問題。 解法 この問題12*12で標準出力から読み込む問題ですが。 島と海のデータがファイルで与えられる場合、ファイルから読み込むようにすれば。 ファイルサイズが10万行*10万列とかで島のサイズが数万*数万とかになっても。 intを64ビット整数型にしておけばスタックオーバーフローしないような計算法で解いてみました。 計算量はBigO(行サイズ*列サイズ) 再帰だと末尾再帰を実現できない限りマップサイズが大きな場合は解けません。 #include<stdio.h> #include<set> const int SIZE=12; int main(){ char nowP; while(1){ std::set<int> spentsNo; std::set<int>::reverse_iterator rIt; spentsNo.insert(0); int oldRowMemo[SIZE]={0}; for(int r=0;r<SIZE;r++){ int nowRowMemo[SIZE]={0}; for(int c=0;c<SIZE;c++){ scanf("%c",&nowP); if(nowP=='0'){ oldRowMemo[c]=nowRowMemo[c]=0; continue; } int max=0; if(0<c){ max=nowRowMemo[c-1]; } if(0<r){ max=max>oldRowMemo[c]?max:oldRowMemo[c]; } if(max==0){ rIt=spentsNo.rbegin(); max=(*rIt)+1; spentsNo.insert(max); } nowRowMemo[c]=max; int t=nowRowMemo[c-1]; if(0<c&&t>0&&t<max){ spentsNo.erase(t); } t=oldRowMemo[c]; if(0<r&&t>0&&t<max){ spentsNo.erase(t); } oldRowMemo[c]=max; } scanf("%c",&nowP);//改行読み込み } printf("%d\n",spentsNo.size()-1); if(scanf("%c",&nowP)==EOF)break; } }