AOJ : 2002 - X-Ray Screening System
アルゴリズム
X線写真の前面から、順番にどの種類の荷物が写っているかを深さ優先で試していく。
例えば、サンプルの3番目の場合、
- A->B->C->D の順番で前面から写っている
- A->B->D->C の順番で前面から写っている
- A->C->B->D の順番で前面から写っている
- ・・・
という具合で、すべてのパターンを試していきます。
もし、この探索途中で、Safe であると確信できる並びが見つかったなら、その時点で Safe と出力するようにしました。
プログラム
#include <stdio.h> #define REP(i,n,m) for(i=n;i<m;i++) #define rep(i,n) REP(i,0,n) int h,w; int mt[26][4]; //[i][0]:左端 [1]:右端 [2]:上端 [3]:下端 int used[26]; char t[54][54]; //(a+'A') の文字が (b+'B') の文字より前にあるかの判定 //その判定と同時に, a が長方形であるかも判定する int isFront(int a,int b){ int i,j; REP(i,mt[a][2],mt[a][3]+1){ REP(j,mt[a][0],mt[a][1]+1){ if(t[i][j] == b + 'A' || t[i][j] == '.'){ return 0; } } } return 1; } //Safeであるかどうかの判定 int isSafe(int idx,int rem){ int i,j; int okFlg; if(rem == 0){ //最後の記号が長方形か判定するためにisFrontを使う return isFront(idx,-1); } used[idx] = 1; rep(i,26){ if(mt[i][1]!=-1 && !used[i]){ //今まで使用した記号全てより後ろにあるか判定 okFlg = 1; rep(j,26) if(used[j] && !isFront(j,i)){ okFlg = 0; break; } if(okFlg && isSafe(i,rem-1)) return 1; } } used[idx] = 0; return 0; } int main(void){ int i,j; int n,idx,count; scanf("%d",&n); while(n--){ scanf("%d%d",&h,&w); rep(i,26){ mt[i][0] = w+1; mt[i][1] = -1; mt[i][2] = h+1; mt[i][3] = -1; } count = 0; rep(i,h){ scanf("%s",t[i]); rep(j,w) if(t[i][j] != '.') { idx = t[i][j] - 'A'; //記号の種類カウント if(mt[idx][1] == -1) count++; //記号の左端,右端,上端,下端を更新 if(mt[idx][0] > j) mt[idx][0] = j; if(mt[idx][1] < j) mt[idx][1] = j; if(mt[idx][2] > i) mt[idx][2] = i; if(mt[idx][3] < i) mt[idx][3] = i; } } rep(i,26) used[i] = 0; rep(i,26) if(mt[i][1] != -1 && isSafe(i,count-1)) break; printf("%s\n",count!=0 && i==26 ? "SUSPICIOUS" : "SAFE"); } return 0; }