Problem:
Problem H: Caterpillar
とある天空都市に住む大学生のGは、芋虫のいも太郎を飼っている。  彼は、いも太郎に最短歩数で全てのえさを順番に食べるように躾けをした。彼の友人であるあなたは、彼からいも太郎が本当に躾けられているかどうかを調べて欲しいと依頼されたので、プログラムを書くことにした。
Problem
複数の障害物とエサがグリッド状のエリア内に存在する。頭と 5 つの胴体を持つ芋虫がこのエリアを探索する。芋虫が順番に最後までエサを食べたときの最小の歩数を求めよ。
ただし全てのエサを食べることが不可能な場合は -1 を出力すること。なお、エサの上に芋虫の頭が重なったとき、エサを食べることができる。
エリアは以下の文字で構成される。
何もないマス -> ‘.’
障害物 -> ‘#’
エサ -> ‘1’, ‘2’, ..., ‘9’
芋虫の初期位置 -> 頭 ‘S’, 胴体 ‘a’, ‘b’, ‘c’, ‘d’, ‘e’
芋虫は頭 ’S’ から 5 つの胴体 ‘a’, ‘b’, ‘c’, ‘d’, ‘e’ と 順に上下左右の 4 方向に隣接して、それらが連なって構成される。
例えば、芋虫の構成を表したとき、以下の (1) は正しい芋虫の構成であるが、 (2) や (3) のような構成はありえない。
(1) 正しい
.bc
Sad
..e

(2) eが存在しない
Sab
.dc

(3) "Sab" と "cde" とで芋虫が切断されている
Sab
cde
(1) のような正しい芋虫の構成は、入力で与えられた状態から任意の回数の芋虫の移動の間、一貫して保たれる。
つまり、芋虫の頭が、隣接している 4 つのマスのうちのいずれかの空いているマスに一歩進むと、その後に続いて 1 番目の胴体は頭が元あったマスへ動き、2 番目の胴体は 1 番目の胴体が元あったマスへ、 3 番目は 2 番目の元へ‥… というように頭の軌跡をたどるように胴体が動く。以下は、１マス左へ動くときの例である。
移動前    移動後
......   ......
...bc.   ...cd.
..Sad.   .Sabe.
....e.   ......
芋虫の移動できる場所は以下のように定められている。
芋虫は自分の胴体、障害物、エリア外を移動することは出来ない。ただしエサの上を、そのエサを食べずに移動することは出来る。
移動前に胴体が進む先にあった場合でも、移動後に頭と胴体が重ならないならば移動できる。
Input
H
W
N
area
入力は
H + 1
行で与えられる。1行目には 3つの整数
H
,
W
,
N
(
2 ≤ H ≤ 10, 2 ≤ W ≤ 10, 1 ≤ N ≤ 9
) が書かれている。
H
はエリアの高さ、
W
は幅、
N
がエサの個数を表す  ( このとき
6 + N ≤ H × W
が必ず成立する ) 。
2 行目から
H + 1
行目までの各行には ´S´,´1´, 2´ , … ´9´,´a´,´b´,´c´,´d´,´e´,´#´,´.´ からなる
W
文字の文字列が書かれており，各々がエリアの各区画の状態を表している。また ´S´,´a´,´b´,´c´,´d´,´e´ は芋虫の初期状態を表している。初期状態の芋虫に覆われるようにしてエサや障害物は存在しない。また、芋虫の初期位置およびエサの位置は正しく入力されることが保証されている。
Output
芋虫がエサを順番通りに食べたときの最小の歩数、またそれが不可能なら -1 を出力せよ。
Sample Input1
5 8 3
#.......
#.####2#
#.#.3..#
#.######
.1Sabcde
Sample Output1
14
Sample Input2
2 6 2
.1.baS
.2.cde
Sample Output2
7
Sample Input3
2 6 2
.1#baS
.2.cde
Sample Output3
-1

Submitted solutions:

code_snippet: #include <bits/stdc++.h>

using namespace std;

typedef pair<int,int> pii;

int H,W,N;
char field[51][51];
const int dy[]={-1,0,0,1};
const int dx[]={0,-1,1,0};
pii esas[11];
int d[11][11][11][4][4][4][4][4];

int getAng(int cy,int cx,int ny,int nx){
  if(ny-cy==-1)return 0;
  else if(nx-cx==-1)return 1;
  else if(nx-cx==1)return 2;
  return 3;
}

pii calcNxtPoint(int cy,int cx,int ang){
  return pii(cy+dy[ang],cx+dx[ang]);
}

struct Sit{
  int cost;
  int heady,headx;
  int pos;
  int ary[5];
  pii poses[5];
  Sit(int pos_,int hy,int hx,int a,int b,int c,int d,int e,int cost_){
    pos=pos_;
    heady=hy;
    headx=hx;
    ary[0]=a;
    ary[1]=b;
    ary[2]=c;
    ary[3]=d;
    ary[4]=e;
    cost=cost_;
  }
  Sit(){
    cost=0;
    pos=0;
  }
  void update_ary(){
    for(int i=0;i<5;i++){
      if(i==0)ary[i]=getAng(heady,headx,poses[0].first,poses[0].second);
      else ary[i]=getAng(poses[i-1].first,poses[i-1].second,poses[i].first,poses[i].second);
    }
  }
  bool operator<(const Sit &sit)const{
    return this->cost>sit.cost;
  }
};

int main(){

  cin>>H>>W>>N;
  Sit start_sit;
  for(int i=0;i<H;i++){
    for(int j=0;j<W;j++){
      cin>>field[i][j];
      if(field[i][j]=='S'){
        start_sit.heady=i;
        start_sit.headx=j;
        field[i][j]='.';
      }
      else if(field[i][j]>='a'&&field[i][j]<='e'){
        int pos=field[i][j]-'a';
        start_sit.poses[pos]=pii(i,j);
        field[i][j]='.';
      }
      else if(field[i][j]>='1'&&field[i][j]<='9'){
        int pos=field[i][j]-'1';
        esas[pos]=pii(i,j);
      }
    }
  }
  start_sit.update_ary();
  // dijkstra
  queue<Sit> pq;
  pq.push(start_sit);
  memset(d,0x7f,sizeof(d));
  d[start_sit.pos][start_sit.heady][start_sit.headx][start_sit.ary[0]][start_sit.ary[1]][start_sit.ary[2]][start_sit.ary[3]][start_sit.ary[4]]=0;
  while(pq.size()){
    Sit csit=pq.front();pq.pop();
    const int ccost=csit.cost;
    const int cpos=csit.pos;
    const int chy=csit.heady;
    const int chx=csit.headx;

    if(cpos==N){
      cout<<ccost<<endl;
      return 0;
    }
    
    int cary[5];
    for(int i=0;i<5;i++)
      cary[i]=csit.ary[i];
    pii bodys[5];
    // caryの情報から，頭以外の座標を復元
    for(int i=0;i<5;i++){
      if(i==0)bodys[i]=calcNxtPoint(chy,chx,cary[i]);
      else bodys[i]=calcNxtPoint(bodys[i-1].first,bodys[i-1].second,cary[i]);
    }
    for(int i=0;i<4;i++){
      int nhy=chy+dy[i];
      int nhx=chx+dx[i];
      // 頭が動けるという条件
      if(nhy>=0&&nhx>=0&&nhy<H&&nhx<W&&field[nhy][nhx]!='#'){
        // bodyを次の場所へ動かし、条件を満たすか調べる
        // 頭の座標とbodyの座標が一致してはいけない
        pii nbodys[5];
        nbodys[0]=pii(chy,chx);
        for(int i=1;i<5;i++)nbodys[i]=bodys[i-1];
        bool isHead=false;
        for(int i=0;i<5;i++){
          if(nbodys[i].first==nhy&&nbodys[i].second==nhx)
            isHead=true;
        }
        if(isHead)continue;
        // 頭の座標が大丈夫なら，次は頭に餌があるかどうかを調べる
        int npos=cpos;
        if(esas[cpos]==pii(nhy,nhx))npos++;
        int ncost=ccost+1;
        Sit nsit;
        nsit.pos=npos;
        nsit.heady=nhy;
        nsit.headx=nhx;
        nsit.cost=ncost;
        for(int i=0;i<5;i++)
          nsit.poses[i]=nbodys[i];
        nsit.update_ary();
        int nary[5];
        for(int i=0;i<5;i++)
          nary[i]=nsit.ary[i];
        // ここで、コストを更新できるか調べる
        if(d[npos][nhy][nhx][nary[0]][nary[1]][nary[2]][nary[3]][nary[4]]>ncost){
          d[npos][nhy][nhx][nary[0]][nary[1]][nary[2]][nary[3]][nary[4]]=ncost;
          pq.push(nsit);
        }
      }
    }
  }

  cout<<-1<<endl;
  
  return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 6744
final_rank: 2

code_snippet: #include <iostream>
#include <queue>
#include <cassert>
#include <map>
#include <vector>
using namespace std;

char c[12][12];

int dx[] = {-1,0,1,0};
int dy[] = {0,1,0,-1};

int memo[12][12][12][1024];

struct NODE{
	int next;
	int x,y,prev;
	int cost;
	NODE(int x,int y,int prev,int next,int cost) : x(x) , y(y) , prev(prev) , next(next), cost(cost) {}
};

int dir(pair<int,int> a,pair<int,int> b){
	int ddx = a.first - b.first;
	int ddy = a.second - b.second;
	if( ddx == 0 ) return ddy < 0 ? 3 : 1;
	else if( ddy == 0 ) return ddx < 0 ? 0 : 2;
	else assert(0);
}

int atamaga[12][12];
int main(){
	for(int i = 0 ; i < 12 ; i++)
		for(int j = 0 ; j < 12 ; j++)
			c[i][j] = '#';

	int H,W,N;
	cin >> H >> W >> N;
	for(int i = 0 ; i < H ; i++){
		for(int j = 0 ; j < W ; j++){
			cin >> c[i+1][j+1];
		}
	}
	map<char,pair<int,int> >tmp;
	for(int i = 1 ; i <= H ; i++){
		for(int j = 1 ; j <= W ; j++){
			tmp[c[i][j]] = make_pair(j,i);
		}
	}
	string table = "edcbaS";
	int initdir = 0;
	for(int i = 0 ; i+1 < table.size() ; i++){
		initdir = initdir * 4 + dir(tmp[table[i+1]],tmp[table[i]]);
	}
	for(int i = 0 ; i < table.size() ; i++){
		int x = tmp[table[i]].first;
		int y = tmp[table[i]].second;
		c[y][x] = '.';
	}
	for(int i = 1 ; i <= N ; i++){
		int x = tmp['0'+i].first;
		int y = tmp['0'+i].second;
		atamaga[y][x] = i;
		c[y][x] = '.';
	}
	queue<NODE> Q;
	Q.push(NODE(tmp['S'].first,tmp['S'].second,initdir,1,0));
	while(Q.size()){
		NODE q = Q.front(); Q.pop();
		if( memo[q.y][q.x][q.next][q.prev]++ ) continue;
		if( q.next > N ){
			cout << q.cost << endl;
			return 0;
		}
		vector< pair<int,int> > dont;
		int tx = q.x , ty = q.y;
		int oo = q.prev;
		dont.push_back(make_pair(tx,ty));
		for(int i = 0 ; i < 4 ; i++){

			int dirdir = (oo+2) % 4;
			oo /= 4;
			tx += dx[dirdir];
			ty += dy[dirdir];
			dont.push_back(make_pair(tx,ty));
		}
		
		for(int i = 0 ; i < 4 ; i++){
			int tx = q.x + dx[i] , ty = q.y + dy[i];
			if( c[ty][tx] == '#' ) continue;
			int flag = 1;
			for(int j = 0 ; j < dont.size() ; j++)
				if( dont[j] == make_pair(tx,ty) ){
					flag = 0; break;
				}
			if(!flag) continue;
			Q.push(NODE(tx,ty,(q.prev*4+(i))%1024,q.next+(q.next==atamaga[ty][tx]),q.cost+1));
		}
		
	}
	cout << -1 << endl;
	
	
	
}
accuracy: 1
time_ms: 10
memory_kb: 6368
final_rank: 1

code_snippet: #include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <climits>
#include <cfloat>
#include <ctime>
#include <cassert>
#include <map>
#include <utility>
#include <set>
#include <iostream>
#include <memory>
#include <string>
#include <vector>
#include <algorithm>
#include <functional>
#include <sstream>
#include <complex>
#include <stack>
#include <queue>
#include <numeric>
#include <list>
#include <iomanip>
#include <fstream>
#include <bitset>

#ifdef LOCAL
#include "local.h"
#endif

using namespace std;

#define rep(i, n) for (int i = 0; i < (int)(n); ++i)
#define all(a) (a).begin(), (a).end()
#define clr(a, x) memset(a, x, sizeof(a))
#define sz(a) ((int)(a).size())
#define mp(a, b) make_pair(a, b)
#define ten(n) ((long long)(1e##n))

template <typename T, typename U> void upmin(T& a, const U& b) { a = min<T>(a, b); }
template <typename T, typename U> void upmax(T& a, const U& b) { a = max<T>(a, b); }
template <typename T> void uniq(T& a) { sort(a.begin(), a.end()); a.erase(unique(a.begin(), a.end()), a.end()); }
template <class T> string to_s(const T& a) { ostringstream os; os << a; return os.str(); }
template <class T> T to_T(const string& s) { istringstream is(s); T res; is >> res; return res; }
void fast_io() { cin.tie(0); ios::sync_with_stdio(false); }
bool in_rect(int x, int y, int w, int h) { return 0 <= x && x < w && 0 <= y && y < h; }

typedef long long ll;
typedef pair<int, int> pint;

const int dx[] = { 0, 1, 0, -1 };
const int dy[] = { 1, 0, -1, 0 };


int main()
{
    int h, w, n;
    cin >> h >> w >> n;
    char c[16][16];
    rep(y, h)
        cin >> c[y];

    vector<pint> start_imo(6);
    const char* imoimo = "Sabcde";
    rep(y, h) rep(x, w)
    {
        if (isalpha(c[y][x]))
            start_imo[strchr(imoimo, c[y][x]) - imoimo] = pint(x, y);
    }

    int res = -1;
    map<pair<int, vector<pint>>, int> dp;
    queue<pair<int, vector<pint>>> q;
    q.push(make_pair(0, start_imo));
    while (!q.empty())
    {
        const int esa = q.front().first;
        const vector<pint> imo = q.front().second;
        const int ncost = dp[q.front()] + 1;
        q.pop();
        assert(imo.size() == 6);

        rep(dir, 4)
        {
            int nx = imo[0].first + dx[dir];
            int ny = imo[0].second + dy[dir];
            if (in_rect(nx, ny, w, h) && c[ny][nx] != '#' &&
                count(imo.begin() + 1, imo.begin() + 5, pint(nx, ny)) == 0)
            {
                vector<pint> nimo;
                nimo.push_back(pint(nx, ny));
                rep(i, 5)
                    nimo.push_back(imo[i]);

                int nesa = esa;
                if (c[ny][nx] - '1' == esa)
                    ++nesa;

                if (nesa == n)
                {
                    res = ncost;
                    goto end;
                }

                auto next = make_pair(nesa, nimo);
                if (!dp.count(next))
                {
                    dp[next] = ncost;
                    q.push(next);
                }
            }
        }
    }
end:;
    cout << res << endl;
}
accuracy: 1
time_ms: 50
memory_kb: 5968
final_rank: 3

code_snippet: #include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <climits>
#include <cfloat>
#include <ctime>
#include <cassert>
#include <map>
#include <utility>
#include <set>
#include <iostream>
#include <memory>
#include <string>
#include <vector>
#include <algorithm>
#include <functional>
#include <sstream>
#include <complex>
#include <stack>
#include <queue>
#include <numeric>
#include <list>
#include <iomanip>
#include <fstream>
#include <bitset>

#ifdef LOCAL
#include "local.h"
#endif

using namespace std;

#define rep(i, n) for (int i = 0; i < (int)(n); ++i)
#define all(a) (a).begin(), (a).end()
#define clr(a, x) memset(a, x, sizeof(a))
#define sz(a) ((int)(a).size())
#define mp(a, b) make_pair(a, b)
#define ten(n) ((long long)(1e##n))

template <typename T, typename U> void upmin(T& a, const U& b) { a = min<T>(a, b); }
template <typename T, typename U> void upmax(T& a, const U& b) { a = max<T>(a, b); }
template <typename T> void uniq(T& a) { sort(a.begin(), a.end()); a.erase(unique(a.begin(), a.end()), a.end()); }
template <class T> string to_s(const T& a) { ostringstream os; os << a; return os.str(); }
template <class T> T to_T(const string& s) { istringstream is(s); T res; is >> res; return res; }
void fast_io() { cin.tie(0); ios::sync_with_stdio(false); }
bool in_rect(int x, int y, int w, int h) { return 0 <= x && x < w && 0 <= y && y < h; }

typedef long long ll;
typedef pair<int, int> pint;

const int dx[] = { 0, 1, 0, -1 };
const int dy[] = { 1, 0, -1, 0 };


int main()
{
    int h, w, n;
    cin >> h >> w >> n;
    char c[16][16];
    rep(y, h)
        cin >> c[y];

    vector<pint> start_imo(6);
    const char* imoimo = "Sabcde";
    rep(y, h) rep(x, w)
    {
        if (isalpha(c[y][x]))
            start_imo[strchr(imoimo, c[y][x]) - imoimo] = pint(x, y);
    }

    int res = -1;
    map<pair<int, vector<pint>>, int> dp;
    queue<pair<int, vector<pint>>> q;
    q.push(make_pair(0, start_imo));
    while (!q.empty())
    {
        int esa = q.front().first;
        vector<pint> imo = q.front().second;
        int ncost = dp[q.front()] + 1;
        q.pop();

        rep(dir, 4)
        {
            int nx = imo[0].first + dx[dir];
            int ny = imo[0].second + dy[dir];
            if (in_rect(nx, ny, w, h) && c[ny][nx] != '#' &&
                find(imo.begin() + 1, imo.begin() + 5, pint(nx, ny)) == imo.begin() + 5)
            {
                vector<pint> nimo;
                nimo.push_back(pint(nx, ny));
                for (int i = 0; i < 5; ++i)
                    nimo.push_back(imo[i]);

                int nesa = esa;
                if (c[ny][nx] - '1' == esa)
                    ++esa;

                if (esa == n)
                {
                    res = ncost;
                    goto end;
                }

                auto next = make_pair(esa, nimo);
                if (!dp.count(next))
                {
                    dp[next] = ncost;
                    q.push(next);
                }
            }
        }
    }
end:;
    cout << res << endl;
}
accuracy: 0.07142857142857142
time_ms: 40
memory_kb: 4344
final_rank: 5

code_snippet: #include<bits/stdc++.h>

#define rep(i,n) for(int i=0;i<(int)n;i++)
#define all(c) (c).begin(),(c).end()
#define mp make_pair
#define pb push_back
#define each(i,c) for(__typeof((c).begin()) i=(c).begin();i!=(c).end();i++)
#define dbg(x) cerr<<__LINE__<<": "<<#x<<" = "<<(x)<<endl

using namespace std;

typedef long long ll;
typedef vector<int> vi;
typedef pair<int,int> pi;
const int inf = (int)1e9;
const double INF = 1e12, EPS = 1e-9;

#define F first
#define S second

int h, w, a;
string in[10];

inline bool ok(const vi &x, const vi& y){
	rep(i, 6) rep(j, i) if(x[i] == x[j] && y[i] == y[j]) return 0;
	return 1;
}

int main(){
	
	cin >> h >> w >> a;
	
	vi gy(a), gx(a);
	vi py(6), px(6);
	
	rep(i, h){
		cin >> in[i];
		
		rep(j, w){
			char c = in[i][j];
			
			if(isalpha(c)){
				
				if(c == 'S') py[0] = i, px[0] = j;
				else py[c - 'a' + 1] = i, px[c - 'a' + 1] = j;
			}
			if(isdigit(c)) gy[c - '1'] = i, gx[c - '1'] = j;
		}
	}
	
	set<pair<int, pair<vi, vi> > > s; //esa, pos;
	queue<pair<pi, pair<vi, vi> > > q; //cost, esa, pos
	
	s.insert(mp(0, mp(py, px)));
	q.push(mp(mp(0, 0), mp(py, px)));
	
	while(!q.empty()){
		
		int cost = q.front().F.F;
		int esa = q.front().F.S;
		vi ys = q.front().S.F;
		vi xs = q.front().S.S;
		
		q.pop();
		cost++;
		
		rep(d, 4){
			const int dy[] = {-1, 0, 1, 0}, dx[] = {0, -1, 0, 1};
			int hy = ys[0] + dy[d], hx = xs[0] + dx[d];
			
			if(hy < 0 || hy >= h || hx < 0 || hx >= w) continue;
			if(in[hy][hx] == '#') continue;
			
			vi ny, nx;
			ny.pb(hy); nx.pb(hx);
			rep(i, 5) ny.pb(ys[i]), nx.pb(xs[i]);
			
			if(!ok(ny, nx)) continue;
			
			int nesa = esa;
			if(in[hy][hx] == '1' + esa){
				if(++nesa == a){
					cout << cost << endl;
					return 0;
				}
			}
			
			if(s.count(mp(nesa, mp(ny, nx)))) continue;
			s.insert(mp(nesa, mp(ny, nx)));
			q.push(mp(mp(cost, nesa), mp(ny, nx)));
		}
	}
	cout << -1 << endl;
	
	return 0;
}
accuracy: 1
time_ms: 100
memory_kb: 6440
final_rank: 4