Codeforces Round #44 (Div 2) C. Crossword

問題概要

6つの英大文字からなる単語が与えられる。
これらを使って下のようなクロスワードパズルを作る。

NOD
BAA
YARD
AIRWAY
NEWTON
BURN

BAA...
U.I...
R.R...
NEWTON
..A..O
..YARD

パズルは単語によってちょうど4つの長方形に分割されていなければならない。
このとき、パズルで辞書順で最も最初に来るものを求めよ。
存在しないならば"Impossible"を出力せよ。

解法

問題文からは読み取りにくいが、縦に並ぶ単語が3つ、横に並ぶ単語が3つで、
サンプルのように単語と単語の交点が7つ(両端で交わるのが6つ、途中で交わるのが1つ)
あるようなクロスワードを作ればよいようである。


したがって、単語の位置をnext_permutationなどで6!通り全部試して、クロスワードになっているか判定してやればよい。

ソースコード

string in[6];
vs tmp,ans;

bool ok(int *l){
  if(l[0]!=l[1]+l[2]-1||l[3]!=l[4]+l[5]-1)return 0;
  return 1;
}
bool ck(char *h,char *t){
  if(h[1]!=h[4]||t[4]!=h[0]||t[1]!=h[3])return 0;
  if(t[3]!=h[2]||t[0]!=h[5]||t[2]!=t[5])return 0;
  return 1;
}

void run()
{
  ans.clear();
  int l[6]; char h[6],t[6];
  rep(i,6)getline(cin,in[i]);
  sort(in,in+6);
  do{
    rep(i,6){
      l[i]=in[i].size();
      h[i]=in[i][0]; t[i]=in[i][l[i]-1];
    }
    if(!ok(l)||!ck(h,t)||in[0][l[1]-1]!=in[3][l[4]-1])continue;
    tmp=vs(l[0],string(l[3],'.'));

    rep(i,l[0])tmp[i][l[4]-1]=in[0][i];
    rep(i,l[1])tmp[i][0]=in[1][i];
    rep(i,l[2])tmp[l[0]-l[2]+i][l[3]-1]=in[2][i];
    rep(i,l[3])tmp[l[1]-1][i]=in[3][i];
    rep(i,l[4])tmp[0][i]=in[4][i];
    rep(i,l[5])tmp[l[0]-1][l[3]-l[5]+i]=in[5][i];

    if(ans.empty()||tmp<ans)ans=tmp;
  }while(next_permutation(in,in+6));
 
  if(ans.empty())cout<<"Impossible"<<endl;
  else rep(i,ans.size())cout<<ans[i]<<endl;
}