Problem:
Move On Dice
There is a cube  on a rectangle map with
H
-rows and
W
-columns grid.
Two special squares a start and a goal are marked on the map.
Initially, the cube is on the start square. Let's repeat to roll it and take it to the goal square.
Rolling the cube means  to select one of four edges which touch the map, and push the cube down without detaching the edge from the map.
That is, there are four  directions you can move the cube toward.
Directions where we can roll the cube are limited depending on each square.
An instruction is written in each square and represented by a single character as follows:
'+'
all
'|'
only vertical
'-'
only horizontal
'<'
only to left
'>'
only to right
'^'
only to up
'v'
only to down
'.'
none
Regardless of instructions, it is not allowed to roll the cube to outside of the map.
On each face of the cube, a string is written.
Let's output the string which concatenates strings written  on the  top face seen during the rollings from the start square to the goal square. 
Since there may be multiple paths  that take the cube to the goal square, choose the minimal string in ascending lexicographic order.
Please note that there are cases where  no path exists from the start to the goal, or the cases you can make the lexicographically minimal string infinitely longer.
Input
A data set has following format:
H
W
C
11
...
C
1W
...
C
H1
...
C
HW
T
1
...
T
6
R
S
C
S
R
D
C
D
The first line of the input contains two integers
H
(
1 ≤ H ≤ 12
) and
W
(
1 ≤ W ≤ 12
),  which indicate the number of rows and columns of the map respectively.
The following
W
lines describe the map.
The
j
-th character of the
i
-th line indicates the instruction of the square, which is placed on
i
-th row (from  the top) and
j
-th column (from the left).
Then the following 6 lines describe the strings on each face of the cube.
All of these strings are not empty and shorter than 12 characters (inclusive).
In addition, they only consist of uppercase alphabets or digits.
The faces where the strings are written are given as figure 1.
Initially, the cube is placed on the start square in a direction as the face No. 1 is  facing top and  the upper direction of face No. 1 faces toward the top row of the map.
Figure 1. a net of a cube
The last two lines contain two integers each that indicate the row number and column number of the start square and the goal square in this order.
You can assume that the start square and the goal square are always different.
Output
Print the lexicographically minimal string in a line.
If there is no path, print "no" in a line.
If you can make the lexicographically minimal string infinitely longer, print "infinite" in a line.
Sample Input 1
1 3
+++
6
5
4
3
2
1
1 3
1 1
Output for the Sample Input 1
621
Sample Input 2
1 3
+++
1
2
3
4
5
6
1 3
1 1
Output for the Sample Input 2
infinite
Sample Input 3
1 3
...
1
2
3
4
5
6
1 3
1 1
Output for the Sample Input 3
no
Sample Input 4
3 3
->|
..v
.^<
JAG
2012
SUMMER
HOGE
HOGE
CAMP
1 1
2 2
Output f
...(truncated)

Submitted solutions:

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 99999999999999999
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;



#define SIZE 15
#define NUM 24

struct LOC{
	int row,col;
};

struct Info{
	void set(int arg_row,int arg_col,int arg_state){
		row = arg_row;
		col = arg_col;
		state = arg_state;
	}
	int row,col,state;
};

struct Edge{
	Edge(Info arg_from,Info arg_to){

		from.set(arg_from.row,arg_from.col,arg_from.state);
		to.set(arg_to.row,arg_to.col,arg_to.state);
	}
	Info from,to;
};

//0:上 1:北 2:東 3:西 4:南 5:裏側

class Dice{
public:

	void roll(char dst){
		for(int i = 0; i < 6; i++) work[i] = number[i];
		switch(dst){
		case 'E':
			setNumber(work[3],work[1],work[0],work[5],work[4],work[2]);
			break;
		case 'S':
			setNumber(work[1],work[5],work[2],work[3],work[0],work[4]);
			break;
		case 'N':
			setNumber(work[4],work[0],work[2],work[3],work[5],work[1]);
			break;
		case 'W':
			setNumber(work[2],work[1],work[5],work[0],work[4],work[3]);
			break;
		}
	};

	int getTop(){
		return number[0];
	}

	void setNumber(int n0,int n1,int n2,int n3,int n4,int n5){
		number[0] = n0;
		number[1] = n1;
		number[2] = n2;
		number[3] = n3;
		number[4] = n4;
		number[5] = n5;
	}

	void init(){
		setNumber(0,1,4,2,3,5); ////0:上 1:北 2:東 3:西 4:南 5:裏側
	}

	void copy(Dice arg){

		for(int i = 0; i < 6; i++){
			number[i] = arg.number[i];
		}
	}

	int number[6],work[6];
};

int H,W;
int diff_row[4] = {-1,0,0,1},diff_col[4] = {0,-1,1,0};
char base_map[SIZE][SIZE];
char order[NUM+1] = "NNNNWNNNWNNNENNNENNNWNNN";
string dp[SIZE][SIZE][25];
LOC start,goal;
string words[6];
vector<Dice> DICE;
vector<Edge> edge;


bool rangeCheck(int row,int col){

	return row >= 0 && row <= H-1 && col >= 0 && col <= W-1;
}

int get_state(Dice dice){

	bool FLG;

	for(int i = 0; i < NUM; i++){
		FLG = true;
		for(int k = 0; k < 6; k++){
			if(dice.number[k] != DICE[i].number[k]){
				FLG = false;
				break;
			}
		}
		if(FLG)return i;
	}

	return -1; //must not reach here
}


int main(){

	scanf("%d %d",&H,&W);

	for(int row = 0; row < H; row++){

		scanf("%s",base_map[row]);
	}

	getchar();

	for(int i = 0; i < 6; i++){

		getline(cin, words[i]);
	}

	scanf("%d %d",&start.row,&start.col);
	start.row--;
	start.col--;

	scanf("%d %d",&goal.row,&goal.col);
	goal.row--;
	goal.col--;

	Dice dice;
	dice.init();

	Dice start_dice;
	start_dice.copy(dice);

	//すべての状態を作る
	for(int state = 0; state < NUM; state++){
		dice.roll(order[state]);
		DICE.push_back(dice);
	}

	int start_state = get_state(start_dice);

	for(int row = 0; row < H; row++){
		for(int col = 0; col < W; col++){
			if(base_map[row][col] == '.')continue;
			for(int state = 0; state < 24; state++){
				Info from;
				from.set(row,col,state);

				for(int i = 0; i < 4; i++){

					int next_row = row+diff_row[i];
					int next_col = col+diff_col[i];
					if(!rangeCheck(next_row,next_col))continue;

					Info to;
					Dice tmp;
					tmp.copy(DICE[state]);

					switch(i){
					case 0: //上へ
						if(base_map[row][col] == '+' || base_map[row][col] == '|' || base_map[row][col] == '^'){
							tmp.roll('N');
							to.set(next_row,next_col,get_state(tmp));
							edge.push_back(Edge(from,to));
						}
						break;
					case 1: //左のセルへ
						if(base_map[row][col] == '+' || base_map[row][col] == '-' || base_map[row][col] == '<'){
							tmp.roll('W');
							to.set(next_row,next_col,get_state(tmp));
							edge.push_back(Edge(from,to));
						}
						break;
					case 2: //右のセルへ
						if(base_map[row][col] == '+' || base_map[row][col] == '-' || base_map[row][col] == '>'){
							tmp.roll('E');
							to.set(next_row,next_col,get_state(tmp));
							edge.push_back(Edge(from,to));
						}
						break;
					case 3: //手前のセルへ
						if(base_map[row][col] == '+' || base_map[row][col] == '|' || base_map[row][col] == 'v'){
							tmp.roll('S');
							to.set(next_row,next_col,get_state(tmp));
							edge.push_back(Edge(from,to));
						}
						break;
					}
				}
			}
		}
	}

	for(int row = 0; row < H; row++){
		for(int col = 0; col < W; col++){
			for(int state = 0; state < NUM; state++){
				dp[row][col][state] = "no";
			}
		}
	}

	for(int state = 0; state < NUM; state++){

		dp[goal.row][goal.col][state] = words[DICE[state].getTop()];
	}

	int LIMIT = H*W*20; //適当なしきい値
	//ベルマンフォード
	bool updated;
	int count = 0;

	while(count < LIMIT+1){
		updated = false;

		Info from,to;

		for(int i = 0; i < edge.size(); i++){

			from = edge[i].from;
			to = edge[i].to;

			//★★逆向きに計算するので注意★
			if(dp[to.row][to.col][to.state] == "no")continue;

			string next_str = words[DICE[from.state].getTop()] + dp[to.row][to.col][to.state]; //★★ゴール方向から逆に動く

			if(dp[from.row][from.col][from.state] == "no" || dp[from.row][from.col][from.state] > next_str){

				dp[from.row][from.col][from.state] = next_str;
				updated = true;
				if(count > H*W*10 && from.row == start.row && from.col == start.col && from.state == start_state){ //適当に打ち切り
					printf("infinite\n");
					return 0;
				}
			}
		}
		if(!updated)break;
		count++;
	}

	printf("%s\n",dp[start.row][start.col][start_state].c_str());

	return 0;
}
accuracy: 1
time_ms: 3110
memory_kb: 30752
final_rank: 6

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 99999999999999999
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;



#define SIZE 15
#define NUM 24

struct LOC{
	int row,col;
};

struct Info{
	void set(int arg_row,int arg_col,int arg_state){
		row = arg_row;
		col = arg_col;
		state = arg_state;
	}
	int row,col,state;
};

struct Edge{
	Edge(Info arg_from,Info arg_to){

		from.set(arg_from.row,arg_from.col,arg_from.state);
		to.set(arg_to.row,arg_to.col,arg_to.state);
	}
	Info from,to;
};

//0:上 1:北 2:東 3:西 4:南 5:裏側

class Dice{
public:

	void roll(char dst){
		for(int i = 0; i < 6; i++) work[i] = number[i];
		switch(dst){
		case 'E':
			setNumber(work[3],work[1],work[0],work[5],work[4],work[2]);
			break;
		case 'S':
			setNumber(work[1],work[5],work[2],work[3],work[0],work[4]);
			break;
		case 'N':
			setNumber(work[4],work[0],work[2],work[3],work[5],work[1]);
			break;
		case 'W':
			setNumber(work[2],work[1],work[5],work[0],work[4],work[3]);
			break;
		}
	};

	int getTop(){
		return number[0];
	}

	void setNumber(int n0,int n1,int n2,int n3,int n4,int n5){
		number[0] = n0;
		number[1] = n1;
		number[2] = n2;
		number[3] = n3;
		number[4] = n4;
		number[5] = n5;
	}

	void init(){
		setNumber(0,1,4,2,3,5); ////0:上 1:北 2:東 3:西 4:南 5:裏側
	}

	void copy(Dice arg){

		for(int i = 0; i < 6; i++){
			number[i] = arg.number[i];
		}
	}

	int number[6],work[6];
};

int H,W;
int diff_row[4] = {-1,0,0,1},diff_col[4] = {0,-1,1,0};
char base_map[SIZE][SIZE];
char order[NUM+1] = "NNNNWNNNWNNNENNNENNNWNNN";
string dp[SIZE][SIZE][25];
LOC start,goal;
string words[6];
vector<Dice> DICE;
vector<Edge> edge;


bool rangeCheck(int row,int col){

	return row >= 0 && row <= H-1 && col >= 0 && col <= W-1;
}

int get_state(Dice dice){

	bool FLG;

	for(int i = 0; i < NUM; i++){
		FLG = true;
		for(int k = 0; k < 6; k++){
			if(dice.number[k] != DICE[i].number[k]){
				FLG = false;
				break;
			}
		}
		if(FLG)return i;
	}

	return -1; //must not reach here
}


int main(){

	scanf("%d %d",&H,&W);

	for(int row = 0; row < H; row++){

		scanf("%s",base_map[row]);
	}

	getchar();

	for(int i = 0; i < 6; i++){

		getline(cin, words[i]);
	}

	scanf("%d %d",&start.row,&start.col);
	start.row--;
	start.col--;

	scanf("%d %d",&goal.row,&goal.col);
	goal.row--;
	goal.col--;

	Dice dice;
	dice.init();

	Dice start_dice;
	start_dice.copy(dice);

	//すべての状態を作る
	for(int state = 0; state < NUM; state++){
		dice.roll(order[state]);
		DICE.push_back(dice);
	}

	int start_state = get_state(start_dice);

	for(int row = 0; row < H; row++){
		for(int col = 0; col < W; col++){
			if(base_map[row][col] == '.')continue;
			for(int state = 0; state < 24; state++){
				Info from;
				from.set(row,col,state);

				for(int i = 0; i < 4; i++){

					int next_row = row+diff_row[i];
					int next_col = col+diff_col[i];
					if(!rangeCheck(next_row,next_col))continue;

					Info to;
					Dice tmp;
					tmp.copy(DICE[state]);

					switch(i){
					case 0: //上へ
						if(base_map[row][col] == '+' || base_map[row][col] == '|' || base_map[row][col] == '^'){
							tmp.roll('N');
							to.set(next_row,next_col,get_state(tmp));
							edge.push_back(Edge(from,to));
						}
						break;
					case 1: //左のセルへ
						if(base_map[row][col] == '+' || base_map[row][col] == '-' || base_map[row][col] == '<'){
							tmp.roll('W');
							to.set(next_row,next_col,get_state(tmp));
							edge.push_back(Edge(from,to));
						}
						break;
					case 2: //右のセルへ
						if(base_map[row][col] == '+' || base_map[row][col] == '-' || base_map[row][col] == '>'){
							tmp.roll('E');
							to.set(next_row,next_col,get_state(tmp));
							edge.push_back(Edge(from,to));
						}
						break;
					case 3: //手前のセルへ
						if(base_map[row][col] == '+' || base_map[row][col] == '|' || base_map[row][col] == 'v'){
							tmp.roll('S');
							to.set(next_row,next_col,get_state(tmp));
							edge.push_back(Edge(from,to));
						}
						break;
					}
				}
			}
		}
	}

	for(int row = 0; row < H; row++){
		for(int col = 0; col < W; col++){
			for(int state = 0; state < NUM; state++){
				dp[row][col][state] = "no";
			}
		}
	}

	for(int state = 0; state < NUM; state++){

		dp[goal.row][goal.col][state] = words[DICE[state].getTop()];
	}

	int LIMIT = H*W*10; //適当なしきい値
	//ベルマンフォード
	bool updated;
	int count = 0;

	while(count < LIMIT+10){
		updated = false;

		Info from,to;

		for(int i = 0; i < edge.size(); i++){

			from = edge[i].from;
			to = edge[i].to;

			//★★逆向きに計算するので注意★
			if(dp[to.row][to.col][to.state] == "no")continue;

			string next_str = words[DICE[from.state].getTop()] + dp[to.row][to.col][to.state]; //★★ゴール方向から逆に動く

			if(dp[from.row][from.col][from.state] == "no" || dp[from.row][from.col][from.state] > next_str){

				dp[from.row][from.col][from.state] = next_str;
				updated = true;
				if(count > LIMIT && from.row == start.row && from.col == start.col && from.state == start_state){ //回数が非常に多くて初期状態に辿り着いた場合
					printf("infinite\n");
					return 0;
				}
			}
		}
		if(!updated)break;
		count++;
	}

	printf("%s\n",dp[start.row][start.col][start_state].c_str());

	return 0;
}
accuracy: 0.28169014084507044
time_ms: 3080
memory_kb: 30640
final_rank: 9

code_snippet: #include<stdio.h>
#include<algorithm>
#include<string>
#include<map>
#include<vector>
using namespace std;
char str[20][20];
int dx[]={1,0,-1,0};
int dy[]={0,1,0,-1};
char pt[3][6]={"^<v>","|-|-","++++"};
string men[6];
char in[20];
int td[6][6]={
{1,2,3,4,5,6},
{2,6,3,1,5,4},
{3,2,6,4,1,5},
{4,1,3,6,5,2},
{5,2,1,4,6,3},
{6,2,5,4,3,1},
};
struct wolf{
	int t[6];
	wolf(){}
};
inline bool operator<(const wolf&a,const wolf&b){
	for(int i=0;i<6;i++)if(a.t[i]!=b.t[i])return a.t[i]<b.t[i];
	return false;
}
void rN(wolf &a){
	int tmp=a.t[0];
	a.t[0]=a.t[3];a.t[3]=a.t[5];a.t[5]=a.t[1];a.t[1]=tmp;
}
void rS(wolf &a){
	int tmp=a.t[0];
	a.t[0]=a.t[1];a.t[1]=a.t[5];a.t[5]=a.t[3];a.t[3]=tmp;
}
void rW(wolf &a){
	int tmp=a.t[0];
	a.t[0]=a.t[4];a.t[4]=a.t[5];a.t[5]=a.t[2];a.t[2]=tmp;
}
void rE(wolf &a){
	int tmp=a.t[0];
	a.t[0]=a.t[2];a.t[2]=a.t[5];a.t[5]=a.t[4];a.t[4]=tmp;
}
map<wolf,int>m;
wolf rev[100];
string dis[20][20][100];
int main(){
	int a,b;
	int sz=0;
	for(int i=0;i<6;i++){
		for(int j=0;j<4;j++){
			wolf tmp;
			tmp.t[0]=td[i][0];
			tmp.t[5]=td[i][5];
			for(int k=0;k<4;k++)tmp.t[k+1]=td[i][1+(j+k)%4];
			rev[sz]=tmp;
			m[tmp]=sz++;
		}
	}
	scanf("%d%d",&a,&b);
	//while(scanf("%d%d",&a,&b),a){
		for(int i=0;i<a;i++)scanf("%s",str[i]);
		for(int i=0;i<6;i++){
			scanf("%s",in);
			men[i]=in;
		}
		for(int i=0;i<a;i++)for(int j=0;j<b;j++)for(int k=0;k<sz;k++)
			dis[i][j][k]="~";
		int sr,sc,gr,gc;
		scanf("%d%d%d%d",&sr,&sc,&gr,&gc);
		sr--;sc--;gr--;gc--;
		for(int i=0;i<sz;i++)dis[gr][gc][i]=men[rev[i].t[0]-1];
		int upd=-1;
		for(int i=0;i<a*b*8;i++){
			bool con=false;
			for(int j=0;j<a;j++){
				for(int k=0;k<b;k++){
					for(int l=0;l<sz;l++){
						if(dis[j][k][l][0]=='~')continue;
						wolf at=rev[l];
						for(int d=0;d<4;d++){
							if(j+dx[d]<0||j+dx[d]>=a||k+dy[d]<0||k+dy[d]>=b)continue;
							bool ok=false;
							for(int e=0;e<3;e++)if(pt[e][d]==str[j+dx[d]][k+dy[d]])ok=true;
							if(!ok)continue;
							if(d==0)rS(at);
							if(d==1)rE(at);
							if(d==2)rN(at);
							if(d==3)rW(at);
							int to=m[at];
							if(dis[j+dx[d]][k+dy[d]][to]>men[at.t[0]-1]+dis[j][k][l]){
								dis[j+dx[d]][k+dy[d]][to]=men[at.t[0]-1]+dis[j][k][l];
								if(j+dx[d]==sr&&k+dy[d]==sc&&to==0)upd=i;
								con=true;
							}
							if(d==0)rN(at);
							if(d==1)rW(at);
							if(d==2)rS(at);
							if(d==3)rE(at);
						}
					}
				}
			}
			if(!con)break;
			if(upd>=a*b*4)break;
		}
		if(upd>=a*b*4){
			printf("infinite\n");
			return 0;
		//	continue;
		}
		if(dis[sr][sc][0][0]=='~'){
			printf("no\n");
			return 0;
		//	continue;
		}
		printf("%s\n",dis[sr][sc][0].c_str());
//	}
}
accuracy: 1
time_ms: 890
memory_kb: 17200
final_rank: 3

code_snippet: #include<stdio.h>
#include<algorithm>
#include<string>
#include<map>
#include<vector>
using namespace std;
char str[20][20];
int dx[]={1,0,-1,0};
int dy[]={0,1,0,-1};
char pt[3][6]={"^<v>","|-|-","++++"};
string men[6];
char in[20];
int td[6][6]={
{1,2,3,4,5,6},
{2,6,3,1,5,4},
{3,2,6,4,1,5},
{4,1,3,6,5,2},
{5,2,1,4,6,3},
{6,2,5,4,3,1},
};
struct wolf{
	int t[6];
	wolf(){}
};
inline bool operator<(const wolf&a,const wolf&b){
	for(int i=0;i<6;i++)if(a.t[i]!=b.t[i])return a.t[i]<b.t[i];
	return false;
}
void rN(wolf &a){
	int tmp=a.t[0];
	a.t[0]=a.t[3];a.t[3]=a.t[5];a.t[5]=a.t[1];a.t[1]=tmp;
}
void rS(wolf &a){
	int tmp=a.t[0];
	a.t[0]=a.t[1];a.t[1]=a.t[5];a.t[5]=a.t[3];a.t[3]=tmp;
}
void rW(wolf &a){
	int tmp=a.t[0];
	a.t[0]=a.t[4];a.t[4]=a.t[5];a.t[5]=a.t[2];a.t[2]=tmp;
}
void rE(wolf &a){
	int tmp=a.t[0];
	a.t[0]=a.t[2];a.t[2]=a.t[5];a.t[5]=a.t[4];a.t[4]=tmp;
}
map<wolf,int>m;
wolf rev[100];
string dis[20][20][100];
int main(){
	int a,b;
	int sz=0;
	for(int i=0;i<6;i++){
		for(int j=0;j<4;j++){
			wolf tmp;
			tmp.t[0]=td[i][0];
			tmp.t[5]=td[i][5];
			for(int k=0;k<4;k++)tmp.t[k+1]=td[i][1+(j+k)%4];
			rev[sz]=tmp;
			m[tmp]=sz++;
		}
	}
	scanf("%d%d",&a,&b);
	//while(scanf("%d%d",&a,&b),a){
		for(int i=0;i<a;i++)scanf("%s",str[i]);
		for(int i=0;i<6;i++){
			scanf("%s",in);
			men[i]=in;
		}
		for(int i=0;i<a;i++)for(int j=0;j<b;j++)for(int k=0;k<sz;k++)
			dis[i][j][k]="~";
		int sr,sc,gr,gc;
		scanf("%d%d%d%d",&sr,&sc,&gr,&gc);
		sr--;sc--;gr--;gc--;
		for(int i=0;i<sz;i++)dis[gr][gc][i]=men[rev[i].t[0]-1];
		int upd=-1;
		for(int i=0;i<a*b*48;i++){
			bool con=false;
			for(int j=0;j<a;j++){
				for(int k=0;k<b;k++){
					for(int l=0;l<sz;l++){
						if(dis[j][k][l][0]=='~')continue;
						wolf at=rev[l];
						for(int d=0;d<4;d++){
							if(j+dx[d]<0||j+dx[d]>=a||k+dx[d]<0||k+dx[d]>=b)continue;
							bool ok=false;
							for(int e=0;e<3;e++)if(pt[e][d]==str[j+dx[d]][k+dy[d]])ok=true;
							if(!ok)continue;
							if(d==0)rS(at);
							if(d==1)rE(at);
							if(d==2)rN(at);
							if(d==3)rW(at);
							int to=m[at];
							if(dis[j+dx[d]][k+dy[d]][to]>men[at.t[0]-1]+dis[j][k][l]){
								dis[j+dx[d]][k+dy[d]][to]=men[at.t[0]-1]+dis[j][k][l];
								if(j+dx[d]==sr&&k+dy[d]==sc&&to==0)upd=i;
								con=true;
							}
							if(d==0)rN(at);
							if(d==1)rW(at);
							if(d==2)rS(at);
							if(d==3)rE(at);
						}
					}
				}
			}
			if(!con)break;
			if(upd>=a*b*24)break;
		}
		if(upd>=a*b*24){
			printf("infinite\n");
			return 0;
		//	continue;
		}
		if(dis[sr][sc][0][0]=='~'){
			printf("no\n");
			return 0;
		//	continue;
		}
		printf("%s\n",dis[sr][sc][0].c_str());
//	}
}
accuracy: 0.056338028169014086
time_ms: 30
memory_kb: 1872
final_rank: 14

code_snippet: #include<cstdio>
#include<string>
#include<vector>
#include<iostream>

#define rep(i,n) for(int i=0;i<(n);i++)

using namespace std;

class dice{
	int a[6];
public:
	dice(){}
	dice(int t,int l,int f,int r,int b,int d){
		a[0]=t; a[1]=l; a[2]=f;
		a[3]=r; a[4]=b; a[5]=d;
	}
	bool operator==(const dice &D)const{
		rep(i,6) if(a[i]!=D.a[i]) return false;
		return true;
	}
	bool operator!=(const dice &D)const{ return !(D==*this); }
	int operator[](int i)const{ return a[i]; }
	int &operator[](int i){ return a[i]; }
	void rotx(){ int tmp=a[0]; a[0]=a[4]; a[4]=a[5]; a[5]=a[2]; a[2]=tmp; }
	void roty(){ int tmp=a[0]; a[0]=a[1]; a[1]=a[5]; a[5]=a[3]; a[3]=tmp; }
	void rotz(){ int tmp=a[1]; a[1]=a[4]; a[4]=a[3]; a[3]=a[2]; a[2]=tmp; }
};

vector<dice> get_all(dice D){
	vector<dice> res;
	rep(i,6){
		rep(j,4){
			res.push_back(D);
			D.rotz();
		}
		if(i%2==0) D.rotx();
		else       D.roty();
	}
	return res;
}

struct node{
	int y,x,id; // y, x, dice direction
};

int main(){
	int h,w; cin>>h>>w;
	string B[12];
	rep(y,h) cin>>B[y];
	string label[6];
	rep(i,6) cin>>label[i];
	int sx,sy,gx,gy; cin>>sy>>sx>>gy>>gx; sx--; sy--; gx--; gy--;

	vector<dice> S=get_all(dice(0,1,2,3,4,5));
	vector< pair<node,node> > E;
	rep(y,h) rep(x,w) rep(id,24) {
		// y--
		if(y>0 && (B[y][x]=='+' || B[y][x]=='|' || B[y][x]=='^')){
			dice D=S[id];
			D.rotx(); D.rotx(); D.rotx();
			int id2;
			for(id2=0;D!=S[id2];id2++);
			E.push_back(make_pair((node){y,x,id},(node){y-1,x,id2}));
		}
		// y++
		if(y+1<h && (B[y][x]=='+' || B[y][x]=='|' || B[y][x]=='v')){
			dice D=S[id];
			D.rotx();
			int id2;
			for(id2=0;D!=S[id2];id2++);
			E.push_back(make_pair((node){y,x,id},(node){y+1,x,id2}));
		}
		// x--
		if(x>0 && (B[y][x]=='+' || B[y][x]=='-' || B[y][x]=='<')){
			dice D=S[id];
			D.roty(); D.roty(); D.roty();
			int id2;
			for(id2=0;D!=S[id2];id2++);
			E.push_back(make_pair((node){y,x,id},(node){y,x-1,id2}));
		}
		// x++
		if(x+1<w && (B[y][x]=='+' || B[y][x]=='-' || B[y][x]=='>')){
			dice D=S[id];
			D.roty();
			int id2;
			for(id2=0;D!=S[id2];id2++);
			E.push_back(make_pair((node){y,x,id},(node){y,x+1,id2}));
		}
	}

	int s_id;
	for(s_id=0;S[s_id][0]!=0||S[s_id][4]!=1;s_id++);

	// Bellman-Ford
	string d[12][12][24];
	rep(y,h) rep(x,w) rep(id,24) d[y][x][id]="no";
	rep(id,24) d[gy][gx][id]=label[S[id][0]];

	rep(t,24*h*w+1){
		bool changed=false;
		rep(i,E.size()){
			const node &u=E[i].first,&v=E[i].second;
			string &d_u=d[u.y][u.x][u.id];
			string &d_v=d[v.y][v.x][v.id];
			if(d_v=="no") continue;

			string d2=label[S[u.id][0]]+d_v;
			if(d_u=="no" || d_u>d2){
				d_u=d2;
				changed=true;
				// if(t==h*w*24 && u.y==sy && u.x==sx && u.id==s_id){
				if(t>h*w*4 && u.y==sy && u.x==sx && u.id==s_id){ // h*w*24 まで見ると TLE するので嘘っぽい上界で適当に打ち切る
					cout<<"infinite"<<endl;
					return 0;
				}
			}
		}
		if(!changed) break;
	}

	cout<<d[sy][sx][s_id]<<endl;

	return 0;
}
accuracy: 1
time_ms: 890
memory_kb: 17424
final_rank: 4

code_snippet: #include <iostream>
#include <string>
#include <algorithm>
#include <vector>
#include <set>
#include <queue>
#include <cstring>
using namespace std;

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

enum FACE { TOP, BOTTOM, FRONT, BACK, LEFT, RIGHT };
template <class T>
class Dice {
public:
  Dice() {
    id[TOP] = 0; id[FRONT] = 3; id[LEFT] = 2;
    id[RIGHT] = 4; id[BACK] = 1; id[BOTTOM] = 5;
  }
  T& operator[] (FACE f) { return id[f]; }
  const T& operator[] (FACE f) const { return id[f]; }
  bool operator==(const Dice<T>& b) const {
    const Dice<T> &a = *this;
    return a[TOP] == b[TOP] && a[BOTTOM] == b[BOTTOM] &&
           a[FRONT] == b[FRONT] && a[BACK] == b[BACK] &&
           a[LEFT] == b[LEFT] && a[RIGHT] == b[RIGHT];
  }

  bool operator<(const Dice<T>& b) const {
	  const Dice<T> &a = *this;

	  if(a[TOP] != b[TOP]) return a[TOP] < b[TOP];
	  if(a[BOTTOM] != b[BOTTOM]) return a[BOTTOM] < b[BOTTOM];
	  if(a[FRONT] != b[FRONT]) return a[FRONT] < b[FRONT];
	  if(a[BACK] != b[BACK]) return a[BACK] < b[BACK];
	  if(a[LEFT] != b[LEFT]) return a[LEFT] < b[LEFT];

	  return a[RIGHT] < b[RIGHT];
  }
  void roll_x() { roll(TOP, BACK, BOTTOM, FRONT); }
  void roll_y() { roll(TOP, LEFT, BOTTOM, RIGHT); }
  void roll_z() { roll(FRONT, RIGHT, BACK, LEFT); }


  void roll_L() { roll(TOP, RIGHT, BOTTOM, LEFT); }
  void roll_R() { roll(TOP, LEFT, BOTTOM, RIGHT); }
  void roll_T() { roll(TOP, FRONT, BOTTOM, BACK); }
  void roll_B() { roll(TOP, BACK, BOTTOM, FRONT); }

  vector<Dice> all_rolls() {
    vector<Dice> ret;
    for (int k = 0; k < 6; (k&1?roll_y():roll_x()),++k)
      for (int i = 0; i < 4; roll_z(), ++i)
        ret.push_back(*this);
    return ret;
  }
  bool equivalent_to(const Dice& di) {
    for (int k = 0; k < 6; (k&1?roll_y():roll_x()),++k)
      for (int i = 0; i < 4; roll_z(), ++i)
        if (*this == di) return true;
    return false;
  }
private:
  void roll(FACE a, FACE b, FACE c, FACE d) {
    T tmp = id[a];
    id[a] = id[b]; id[b] = id[c];
    id[c] = id[d]; id[d] = tmp;
  }
  T var[6];
  int id[6];
};

class State
{
public:
	int x,y,p;
	Dice<int> d;

	State(int x, int y, Dice<int> d, int p = 1)
		:x(x),y(y),d(d),p(p)
	{}

	bool operator<(const State& s) const
	{
		if(x != s.x) return x < s.x;
		if(y != s.y) return y < s.y;
		if(p != s.p) return p < s.p;

		return d < s.d;
	}
};

int W,H;
int xs,ys,xd,yd;

string field[12], alpha[6];
bool reached[12][12][6][6][2];

int dir(char c)
{
	if(c == '+') return 1 + 2 + 4 + 8;
	if(c == '|') return     2 +     8;
	if(c == '-') return 1 +     4    ;
	if(c == '<') return 1            ;
	if(c == '>') return         4    ;
	if(c == '^') return     2        ;
	if(c == 'v') return		        8;

	return 0;
}

void bfs(int sx, int sy, int p)
{
	queue<State> q;
	if(p == 0) {
		q.push(State(sx, sy, Dice<int>()));
	}
	else {
		Dice<int> d;
		vector<Dice<int> > a = d.all_rolls();
		for(int i=0; i<a.size(); i++) {
			q.push(State(sx, sy, a[i]));
		}
	}


	while(!q.empty()) {
		State s=q.front(); q.pop();
		if(reached[s.x][s.y][s.d[TOP]][s.d[LEFT]][p]) continue;
		reached[s.x][s.y][s.d[TOP]][s.d[LEFT]][p] = 1;


		
		for(int i=0; i<4; i++) {
			int tx = s.x + dx[i];
			int ty = s.y + dy[i];

			if(tx < 0 || ty < 0 || tx >= W || ty >= H) continue;

			if(p == 0) {
				int d = dir(field[s.y][s.x]);
				if(! (d >> i & 1) ) continue;
			}
			else {
				int d = dir(field[ty][tx]);
				if(! (d >> (i+2)%4 & 1 ) ) continue;
			}

			Dice<int> td = s.d;
			if(i == 0) td.roll_L();
			if(i == 1) td.roll_T();
			if(i == 2) td.roll_R();
			if(i == 3) td.roll_B();

			if(reached[tx][ty][td[TOP]][td[LEFT]][p]) continue;

			q.push(State(tx, ty, td));

		}
	}
}

string solve()
{
	string res;
	res += alpha[0][0];
	set<State> dice;

	dice.insert(State(xs, ys, Dice<int>(), 1));

	while(1) {
		//最小となる次の状態を見つける
		set<State>::iterator it = dice.begin();
		set<State> next;
		char minc = '_';

		if(res.size() > W*H*12*24) {
			res = "infinite";
			break;
		}

		bool goal = false;

		for(; it != dice.end(); it++) {
			State s = *it;

			if(s.x == xd && s.y == yd && alpha[s.d[TOP]].size() == s.p) goal = true;

			if(alpha[s.d[TOP]].size() > s.p) {
				char c = alpha[s.d[TOP]][s.p];
				if(minc > c) {
					minc = c;
					next.clear();
					next.insert(State(s.x, s.y, s.d, s.p + 1));
				}
				else if(minc == c) {
					next.insert(State(s.x, s.y, s.d, s.p + 1));
				}
			}
			else {
				int d = dir(field[s.y][s.x]);
				for(int i=0; i<4; i++) {
					if(! (d >> i & 1) ) continue;

					int tx = s.x + dx[i];
					int ty = s.y + dy[i];

					if(tx < 0 || ty < 0 || tx >= W || ty >= H) continue;

					Dice<int> td = s.d;
					if(i == 0) td.roll_L();
					if(i == 1) td.roll_T();
					if(i == 2) td.roll_R();
					if(i == 3) td.roll_B();

					if(reached[tx][ty][td[TOP]][td[LEFT]][0] &&
					   reached[tx][ty][td[TOP]][td[LEFT]][1]) {
						   char c = alpha[td[TOP]][0];
						   if(minc > c) {
							   minc = c;
							   next.clear();
							   next.insert(State(tx,ty,td, 1));
						   }
						   else if(minc == c) {
							   next.insert(State(tx,ty,td, 1));
						   }
					}
				}
			}
		}

		if(goal) {
			break;
		}

		if(next.empty()) {
			res = "no";
			break;
		}

		res += minc;
		swap(dice, next);
		
	}

	return res;
}

int main()
{
	cin >> H >> W;
	for(int i=0; i<H; i++)
		cin >> field[i];

	for(int i=0; i<6; i++)
		cin >> alpha[i];

	cin >> ys >> xs;
	cin >> yd >> xd;

	xs--; ys--;
	xd--; yd--;

	memset(reached, 0, sizeof(reached));
	bfs(xs, ys, 0);
	bfs(xd, yd, 1);

	cout << solve() << endl;
}
accuracy: 1
time_ms: 1120
memory_kb: 4836
final_rank: 1

code_snippet: #include <cstdio>
#include <iostream>
#include <sstream>
#include <iomanip>
#include <algorithm>
#include <cmath>
#include <string>
#include <vector>
#include <list>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <bitset>
#include <numeric>
#include <climits>
#include <cfloat>
using namespace std;

unsigned long xor128(){
    static unsigned long x=123456789,y=362436069,z=521288629,w=88675123;
    unsigned long t;
    t=(x^(x<<11));x=y;y=z;z=w; return( w=(w^(w>>19))^(t^(t>>8)) );
}

class Dice
{
public:
    vector<int> pip; // 東南西北上下の目
    Dice(){
        pip.assign(6, -1);
    }
    void roll(int d){ // 東南西北右左に回転
        int dir[][4] = {{4,2,5,0},{4,3,5,1},{4,0,5,2},{4,1,5,3},{0,3,2,1},{0,1,2,3}};
        int tmp = pip[dir[d][0]];
        for(int i=0; i<3; ++i)
            pip[dir[d][i]] = pip[dir[d][i+1]];
        pip[dir[d][3]] = tmp;
    }
    bool operator==(const Dice& d) const{
        return pip == d.pip;
    }
};

class Data
{
public:
    int y, x;
    Dice d;
    Data(int y0, int x0, const Dice& d0){
        y = y0;
        x = x0;
        d = d0;
    }
    int toInt() const{
        return ((y * 14 + x) * 6 + d.pip[0]) * 6 + d.pip[1];
    }
    bool operator<(const Data& d) const{
        return toInt() < d.toInt();
    }
};

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

int main()
{
    int h, w;
    cin >> h >> w;

    vector<string> s(h+2, string(w+2, '.'));
    for(int i=1; i<=h; ++i){
        for(int j=1; j<=w; ++j){
            cin >> s[i][j];
        }
    }
    h += 2;
    w += 2;

    vector<string> face(6);
    for(int i=0; i<6; ++i)
        cin >> face[i];

    int sy, sx, gy, gx;
    cin >> sy >> sx >> gy >> gx;

    Dice init;
    init.pip[0] = 4;
    init.pip[1] = 3;
    init.pip[2] = 2;
    init.pip[3] = 1;
    init.pip[4] = 0;
    init.pip[5] = 5;

    vector<bool> check(14*14*6*6, false);
    queue<Data> q;
    for(int i=0; i<24; ++i){
        init.roll(xor128() % 6);
        Data d(gy, gx, init);
        if(!check[d.toInt()]){
            check[d.toInt()] = true;
            q.push(d);
        }else{
            -- i;
        }
    }

    vector<vector<Data> > edges(14*14*6*6);
    while(!q.empty()){
        Data d0 = q.front();
        q.pop();
        int y0 = d0.y;
        int x0 = d0.x;
        Dice dice0 = d0.d;

        for(int i=0; i<4; ++i){
            int y = y0 + dy[i];
            int x = x0 + dx[i];
            if(s[y][x] != '+'){
                if(i == 0 && s[y][x] != '-' && s[y][x] != '<')
                    continue;
                if(i == 1 && s[y][x] != '|' && s[y][x] != '^')
                    continue;
                if(i == 2 && s[y][x] != '-' && s[y][x] != '>')
                    continue;
                if(i == 3 && s[y][x] != '|' && s[y][x] != 'v')
                    continue;
            }

            Dice dice = dice0;
            dice.roll(i);
            Data d(y, x, dice);

            edges[d.toInt()].push_back(d0);
            if(!check[d.toInt()]){
                check[d.toInt()] = true;
                q.push(d);
            }
        }
    }

    while(init.pip[4] != 0 || init.pip[0] != 4)
        init.roll(xor128() % 6);
    Data d(sy, sx, init);
    if(edges[d.toInt()].size() == 0){
        cout << "no" << endl;
        return 0;
    }

    set<pair<Data, int> > curr;
    curr.insert(make_pair(d, 0));

    string ret;
    for(int i=0; i<42000; ++i){
        char c = 'a';
        for(set<pair<Data, int> >::iterator it=curr.begin(); it!=curr.end(); ++it){
            Data d = it->first;
            int i = d.d.pip[4];
            int j = it->second;
            c = min(c, face[i][j]);
        }

        ret += c;

        set<pair<Data, int> > next;
        for(set<pair<Data, int> >::iterator it=curr.begin(); it!=curr.end(); ++it){
            Data d = it->first;
            int i = d.d.pip[4];
            int j = it->second;
            if(c == face[i][j]){
                if(j == face[i].size() - 1){
                    if(d.y == gy && d.x == gx){
                        cout << ret << endl;
                        return 0;
                    }

                    for(unsigned k=0; k<edges[d.toInt()].size(); ++k){
                        Data d2 = edges[d.toInt()][k];
                        next.insert(make_pair(d2, 0));
                    }
                }else{
                    next.insert(make_pair(d, j+1));
                }
            }
        }

        curr.swap(next);
    }

    cout << "infinite" << endl;
    return 0;
}
accuracy: 1
time_ms: 2760
memory_kb: 5756
final_rank: 5

code_snippet: #include <cstdio>
#include <iostream>
#include <sstream>
#include <iomanip>
#include <algorithm>
#include <cmath>
#include <string>
#include <vector>
#include <list>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <bitset>
#include <numeric>
#include <climits>
#include <cfloat>
using namespace std;

unsigned long xor128(){
    static unsigned long x=123456789,y=362436069,z=521288629,w=88675123;
    unsigned long t;
    t=(x^(x<<11));x=y;y=z;z=w; return( w=(w^(w>>19))^(t^(t>>8)) );
}

class Dice
{
public:
    vector<int> pip; // 東南西北上下の目
    Dice(){
        pip.assign(6, -1);
    }
    void roll(int d){ // 東南西北右左に回転
        int dir[][4] = {{4,2,5,0},{4,3,5,1},{4,0,5,2},{4,1,5,3},{0,3,2,1},{0,1,2,3}};
        int tmp = pip[dir[d][0]];
        for(int i=0; i<3; ++i)
            pip[dir[d][i]] = pip[dir[d][i+1]];
        pip[dir[d][3]] = tmp;
    }
    bool operator==(const Dice& d) const{
        return pip == d.pip;
    }
};

class Data
{
public:
    int y, x;
    Dice d;
    Data(int y0, int x0, const Dice& d0){
        y = y0;
        x = x0;
        d = d0;
    }
    int toInt(){
        return ((y * 14 + x) * 6 + d.pip[4]) * 6 + d.pip[0];
    }
};

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

int main()
{
    int h, w;
    cin >> h >> w;

    vector<string> s(h+2, string(w+2, '.'));
    for(int i=1; i<=h; ++i){
        for(int j=1; j<=w; ++j){
            cin >> s[i][j];
        }
    }
    h += 2;
    w += 2;

    vector<string> face(6);
    for(int i=0; i<6; ++i)
        cin >> face[i];

    int sy, sx, gy, gx;
    cin >> sy >> sx >> gy >> gx;

    Dice init;
    init.pip[0] = 4;
    init.pip[1] = 3;
    init.pip[2] = 2;
    init.pip[3] = 1;
    init.pip[4] = 0;
    init.pip[5] = 5;

    vector<string> dp(14*14*6*6, "no");
    multimap<string, Data> mm;
    for(int i=0; i<24; ++i){
        init.roll(xor128() % 6);
        Data d(gy, gx, init);
        if(dp[d.toInt()] == "no"){
            dp[d.toInt()] = face[init.pip[4]];
            mm.insert(make_pair(face[init.pip[4]], d));
        }else{
            -- i;
        }
    }

    while(!mm.empty()){
        string t0 = mm.begin()->first;
        Data d0 = mm.begin()->second;
        mm.erase(mm.begin());
        if(t0 > dp[d0.toInt()])
            continue;

        int y0 = d0.y;
        int x0 = d0.x;
        Dice dice0 = d0.d;

        for(int i=0; i<4; ++i){
            int y = y0 + dy[i];
            int x = x0 + dx[i];
            if(s[y][x] != '+'){
                if(i == 0 && s[y][x] != '-' && s[y][x] != '<')
                    continue;
                if(i == 1 && s[y][x] != '|' && s[y][x] != '^')
                    continue;
                if(i == 2 && s[y][x] != '-' && s[y][x] != '>')
                    continue;
                if(i == 3 && s[y][x] != '|' && s[y][x] != 'v')
                    continue;
            }

            Dice dice = dice0;
            dice.roll(i);
            Data d(y, x, dice);
            string t = face[dice.pip[4]] + t0;
            if(t.size() > 2000)
                t.resize(2000);

            if(t < dp[d.toInt()]){
                if(y == 1 && x == 3 && dice.pip[4] == 0)
                    y = 1;
                dp[d.toInt()] = t;
                mm.insert(make_pair(t, d));
            }
        }
    }

    while(init.pip[4] != 0 || init.pip[0] != 4)
        init.roll(xor128() % 6);
    Data d(sy, sx, init);

    string ret = dp[d.toInt()];
    if(ret.size() >= 2000)
        cout << "infinite" << endl;
    else
        cout << ret << endl;

    return 0;
}
accuracy: 0.2676056338028169
time_ms: 20
memory_kb: 6164
final_rank: 12

code_snippet: #include <iostream>
#include <algorithm>
using namespace std;
 

// If this structure is used for two-dimensional surface,
// it assumes that the face id[0] faces the positive direction of the Y axis,
// the face id[1] faces the positive direction of the X axis
// and id[2] is top of the dice.
struct Dice {
  int id[6], cnt;
  const static int f[3][3];

  Dice() { init(); }

  void init() {
    for(int i = 0; i < 6; ++i) {
      id[i] = i;
    }
    cnt = 0;
  }

  // type (0:spin, 1:rollX, 2:rollY)
  // dir 1( ccw     neg      pos   )
  //    -1( cw      pos      neg   )
  void rotate(int type, int dir = 1) {
    const int *v = f[type];
    int a,b,c,t; a=v[0]; b=v[1]; c=v[2]; t=id[type];
    if(dir < 0) swap(a,c);
    id[type]=id[a]; id[a]=id[b]; id[b]=id[c]; id[c]=t;
  }

  bool next() {
    ++cnt;
    if(cnt == 24) {
      rotate(0,-1);
      rotate(1,-1);
      cnt = 0;
      return false;
    }
    if(cnt == 4*3) {
      rotate(2,-1);
      rotate(0,-1);
    } else if(cnt%4 == 0) {
      rotate(2);
    } else {
      rotate(0);
    }
    return true;
  }

  void roll(int dir) {
    //const static int dx[] = {1,0,-1,0};
    //const static int dy[] = {0,1,0,-1};
    switch(dir) {
      case 0: rotate(1,-1); break;
      case 1: rotate(2, 1); break;
      case 2: rotate(1, 1); break;
      case 3: rotate(2,-1); break;
    }
  }

  bool operator < (const Dice &d) const {
    for(int i = 0; i < 3; ++i)
      if(id[i] != d.id[i]) return id[i] < d.id[i];
    return false;
  }

  void show() {
    cout << id[4] << " / \\ " << id[5] << endl;
    cout << " /   \\" << endl;
    cout << "|\\ " << id[2] << " /|" << endl;
    cout << "|" << id[0] << "\\ /" << id[1] << "|" << endl;
    cout << " \\ | /" << endl;
    cout << "  \\|/" << endl;
    cout << "   " << id[3] << endl;
  }
};
const int Dice::f[3][3] = {{4,5,1},{3,4,2},{5,3,0}};

//----------------------------------------------------------

#include <map>
#include <vector>
#include <queue>
#include <set>
#include <string>

struct State {
  int i, j;
  Dice dice;

  State() {}
  State(int i, int j, Dice dice)
    : i(i), j(j), dice(dice) {}

  bool operator < (const State &s) const {
    if(i != s.i) return i < s.i;
    if(j != s.j) return j < s.j;
    return dice < s.dice;
  }
};

struct State2 : public State {
  int p;
  State2() {}
  State2(int i, int j, Dice dice, int p)
    : State(i,j,dice), p(p) {}

  bool operator < (const State2 &s) const {
    if(p != s.p) return p < s.p;
    return (State)(*this) < (State)s;
  }
};

const int di[] = {0,1,0,-1};  
const int dj[] = {1,0,-1,0};
const int MAX_H = 13;
const int MAX_W = 13;
const int STATE_NUM = 5000;

int H, W;
int G[MAX_H][MAX_W];
string F[6];
int si, sj, gi, gj;
map<State, int> id;
map<int, State> rid;
set<State> canGoal;

vector<int> E[STATE_NUM], rE[STATE_NUM];

int getId(const State &s) {
  if(!id.count(s)) id[s] = (int)id.size()-1;
  rid[id[s]] = s;
  return id[s];
}

void init() {
  for(int i = 0; i < MAX_H; ++i) {
    for(int j = 0; j < MAX_W; ++j) {
      Dice dice;
      do {
        getId(State(i,j,dice));
      } while(dice.next());
    }
  }
}

void make() {
  for(int i = 0; i < STATE_NUM; ++i) {
    E[i].clear();
    rE[i].clear();
  }
  for(int i = 0; i < H; ++i) {
    for(int j = 0; j < W; ++j) {
      Dice dice;
      do {
        State s(i,j,dice);
        for(int d = 0; d < 4; ++d) {
          if(G[i][j] & (1<<d)) ; else continue;
          int ni = i + di[d];
          int nj = j + dj[d];
          if(ni < 0 || ni >= H) continue;
          if(nj < 0 || nj >= W) continue;
          Dice ndice = dice;
          ndice.roll(d);
          State t(ni,nj,ndice);
          E[id[s]].push_back(id[t]);
          rE[id[t]].push_back(id[s]);
        }
      } while(dice.next());
    }
  }
}

void bfs(State s, const vector<int> e[], set<State> &vis) {
  queue<State> que;
  que.push(s);
  vis.insert(s);
  while(!que.empty()) {
    s = que.front();
    que.pop();
    int sid = id[s];
    for(int i = 0; i < e[sid].size(); ++i) {
      State t = rid[e[sid][i]];
      if(vis.count(t)) continue;
      que.push(t);
      vis.insert(t);
    }
  }
}

int main() {
  init();
  while(cin >> H >> W) {
    for(int i = 0; i < H; ++i) {
      for(int j = 0; j < W; ++j) {
        char c;
        cin >> c;
        int &g = G[i][j];
        switch(c) {
          case '+': g = (1<<4)-1; break;
          case '|': g = (1<<1)|(1<<3); break;
          case '-': g = (1<<0)|(1<<2); break;
          case '<': g = (1<<2); break;
          case '>': g = (1<<0); break;
          case '^': g = (1<<3); break;
          case 'v': g = (1<<1); break;
          case '.': g = 0; break;
        }
      }
    }
    cin >> F[2];
    cin >> F[5];
    cin >> F[4];
    cin >> F[0];
    cin >> F[1];
    cin >> F[3];
    cin >> si >> sj;
    cin >> gi >> gj;
    --si; --sj; --gi; --gj;
    make();

    set<State2> vis[2];
    string res;
    set<State> can[2];
    bfs(State(si,sj,Dice()), E, can[0]);
    {
      Dice dice;
      do {
        bfs(State(gi,gj,dice), rE, can[1]);
      } while(dice.next());
    }

    {
      State2 s(si,sj,Dice(),0);
      if(can[0].count(s) && can[1].count(s)) {
        vis[0].insert(s);
      } else {
        cout << "no" << endl;
        continue;
      }
    }
    res = "";

    for(int p = 0; ; p = 1-p) {
      int n = 1-p;
      char mini = 127;
      for(set<State2>::iterator it = vis[p].begin();
          it != vis[p].end(); ++it) {
        if(it->i == gi && it->j == gj &&
           it->p == F[it->dice.id[2]].size()) {
          res += '$';
          break;
        }

        if(it->p == F[it->dice.id[2]].size()) {
          int sid = id[*it];
          for(int i = 0; i < E[sid].size(); ++i) {
            State t = rid[E[sid][i]];
            if(can[0].count(t) && can[1].count(t)) ; else continue;
            if(F[t.dice.id[2]][0] <= mini) {
              if(F[t.dice.id[2]][0] < mini) {
                vis[n].clear();
                mini = F[t.dice.id[2]][0];
              }
              vis[n].insert(State2(t.i, t.j, t.dice, 1));
            }
          }
        } else {
          if(F[it->dice.id[2]][it->p] <= mini) {
            if(F[it->dice.id[2]][it->p] < mini) {
              vis[n].clear();
              mini = F[it->dice.id[2]][it->p];
            }
            State2 tmp = *it;
            ++tmp.p;
            vis[n].insert(tmp); 
          }
        }
      }

      if(*res.rbegin() == '$') {
        res = res.substr(0, (int)res.size()-1);
        break;
      }
      if(mini == 127) {
        res = "no";
        break;
      }
      if(res.size() > STATE_NUM*13) {
        res = "infinite";
        break;
      }
      res += mini;
    }
    cout << res << endl;
  }
  return 0;
}
accuracy: 1
time_ms: 1760
memory_kb: 5308
final_rank: 2

code_snippet: #include <iostream>
#include <algorithm>
using namespace std;
 

// If this structure is used for two-dimensional surface,
// it assumes that the face id[0] faces the positive direction of the Y axis,
// the face id[1] faces the positive direction of the X axis
// and id[2] is top of the dice.
struct Dice {
  int id[6], cnt;
  const static int f[3][3];

  Dice() { init(); }

  void init() {
    for(int i = 0; i < 6; ++i) {
      id[i] = i;
    }
    cnt = 0;
  }

  // type (0:spin, 1:rollX, 2:rollY)
  // dir 1( ccw     neg      pos   )
  //    -1( cw      pos      neg   )
  void rotate(int type, int dir = 1) {
    const int *v = f[type];
    int a,b,c,t; a=v[0]; b=v[1]; c=v[2]; t=id[type];
    if(dir < 0) swap(a,c);
    id[type]=id[a]; id[a]=id[b]; id[b]=id[c]; id[c]=t;
  }

  bool next() {
    ++cnt;
    if(cnt == 24) {
      rotate(0,-1);
      rotate(1,-1);
      cnt = 0;
      return false;
    }
    if(cnt == 4*3) {
      rotate(2,-1);
      rotate(0,-1);
    } else if(cnt%4 == 0) {
      rotate(2);
    } else {
      rotate(0);
    }
    return true;
  }

  void roll(int dir) {
    //const static int dx[] = {1,0,-1,0};
    //const static int dy[] = {0,1,0,-1};
    switch(dir) {
      case 0: rotate(1,-1); break;
      case 1: rotate(2, 1); break;
      case 2: rotate(1, 1); break;
      case 3: rotate(2,-1); break;
    }
  }

  bool operator < (const Dice &d) const {
    for(int i = 0; i < 3; ++i)
      if(id[i] != d.id[i]) return id[i] < d.id[i];
    return false;
  }

  void show() {
    cout << id[4] << " / \\ " << id[5] << endl;
    cout << " /   \\" << endl;
    cout << "|\\ " << id[2] << " /|" << endl;
    cout << "|" << id[0] << "\\ /" << id[1] << "|" << endl;
    cout << " \\ | /" << endl;
    cout << "  \\|/" << endl;
    cout << "   " << id[3] << endl;
  }
};
const int Dice::f[3][3] = {{4,5,1},{3,4,2},{5,3,0}};

//----------------------------------------------------------

#include <map>
#include <vector>
#include <queue>
#include <set>
#include <string>

struct State {
  int i, j;
  Dice dice;

  State() {}
  State(int i, int j, Dice dice)
    : i(i), j(j), dice(dice) {}

  bool operator < (const State &s) const {
    if(i != s.i) return i < s.i;
    if(j != s.j) return j < s.j;
    return dice < s.dice;
  }
};

struct State2 : public State {
  int p;
  State2() {}
  State2(int i, int j, Dice dice, int p)
    : State(i,j,dice), p(p) {}

  bool operator < (const State2 &s) const {
    if(p != s.p) return p < s.p;
    return (State)(*this) < (State)s;
  }
};

const int di[] = {0,1,0,-1};  
const int dj[] = {1,0,-1,0};
const int MAX_H = 13;
const int MAX_W = 13;
const int STATE_NUM = 5000;

int H, W;
int G[MAX_H][MAX_W];
string F[6];
int si, sj, gi, gj;
map<State, int> id;
map<int, State> rid;

vector<int> E[STATE_NUM];

int getId(const State &s) {
  if(!id.count(s)) id[s] = (int)id.size()-1;
  rid[id[s]] = s;
  return id[s];
}

void init() {
  for(int i = 0; i < MAX_H; ++i) {
    for(int j = 0; j < MAX_W; ++j) {
      Dice dice;
      do {
        getId(State(i,j,dice));
      } while(dice.next());
    }
  }
}

void make() {
  for(int i = 0; i < STATE_NUM; ++i) E[i].clear();
  for(int i = 0; i < H; ++i) {
    for(int j = 0; j < W; ++j) {
      Dice dice;
      do {
        State s(i,j,dice);
        for(int d = 0; d < 4; ++d) {
          if(G[i][j] & (1<<d)) ; else continue;
          int ni = i + di[d];
          int nj = j + dj[d];
          if(ni < 0 || ni >= H) continue;
          if(nj < 0 || nj >= W) continue;
          Dice ndice = dice;
          ndice.roll(d);
          State t(ni,nj,ndice);
          E[id[s]].push_back(id[t]);
        }
      } while(dice.next());
    }
  }
}

bool bfs(int si, int sj, int gi, int gj) {
  if(si == gi && sj == gj) return true;
  queue<State> que;
  set<State> vis;
  State s(si,sj,Dice());
  que.push(s);
  vis.insert(s);
  while(!que.empty()) {
    s = que.front();
    que.pop();
    int sid = id[s];
    for(int i = 0; i < E[sid].size(); ++i) {
      State t = rid[E[sid][i]];
      if(vis.count(t)) continue;
      if(t.i == gi && t.j == gj) return true;
      que.push(t);
      vis.insert(t);
    }
  }
  return false;
}

int main() {
  init();
  while(cin >> H >> W) {
    for(int i = 0; i < H; ++i) {
      for(int j = 0; j < W; ++j) {
        char c;
        cin >> c;
        int &g = G[i][j];
        switch(c) {
          case '+': g = (1<<4)-1; break;
          case '|': g = (1<<1)|(1<<3); break;
          case '-': g = (1<<0)|(1<<2); break;
          case '<': g = (1<<2); break;
          case '>': g = (1<<0); break;
          case '^': g = (1<<3); break;
          case 'v': g = (1<<1); break;
          case '.': g = 0; break;
        }
      }
    }
    cin >> F[2];
    cin >> F[5];
    cin >> F[4];
    cin >> F[0];
    cin >> F[1];
    cin >> F[3];
    cin >> si >> sj;
    cin >> gi >> gj;
    --si; --sj; --gi; --gj;
    make();

    set<State2> vis[2];
    string res;

    vis[0].insert(State2(si,sj,Dice(),0));
    res = "";

    if(!bfs(si,sj,gi,gj)) {
      cout << "no" << endl;
      continue;
    }
    for(int t = 0; ; t = 1-t) {
      int n = 1-t;
      char mini = 127;

      for(set<State2>::iterator it = vis[t].begin();
          it != vis[t].end(); ++it) {
        if(it->i == gi && it->j == gj &&
           it->p == F[it->dice.id[2]].size()) {
          res += '$';
          break;
        }

        if(it->p == F[it->dice.id[2]].size()) {
          int sid = id[*it];
          for(int i = 0; i < E[sid].size(); ++i) {
            State t = rid[E[sid][i]];
            if(F[t.dice.id[2]][0] <= mini) {
              if(F[t.dice.id[2]][0] < mini) {
                vis[n].clear();
                mini = F[t.dice.id[2]][0];
              }
              vis[n].insert(State2(t.i, t.j, t.dice, 1));
            }
          }
        } else {
          if(F[it->dice.id[2]][it->p] <= mini) {
            if(F[it->dice.id[2]][it->p] < mini) {
              vis[n].clear();
              mini = F[it->dice.id[2]][it->p];
            }
            State2 tmp = *it;
            ++tmp.p;
            vis[n].insert(tmp); 
          }
        }
      }

      if(*res.rbegin() == '$') {
        res = res.substr(0, (int)res.size()-1);
        break;
      }
      if(mini == 127) {
        res = "no";
        break;
      }
      if(res.size() > STATE_NUM*13) {
        res = "infinite";
        break;
      }
      res += mini;
    }
    cout << res << endl;
  }
  return 0;
}
accuracy: 0.5915492957746479
time_ms: 1420
memory_kb: 4664
final_rank: 8

code_snippet: #include <cstdio>
#include <iostream>
#include <sstream>
#include <iomanip>
#include <algorithm>
#include <cmath>
#include <string>
#include <vector>
#include <list>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <bitset>
#include <numeric>
#include <climits>
#include <cfloat>
using namespace std;

unsigned long xor128(){
    static unsigned long x=123456789,y=362436069,z=521288629,w=88675123;
    unsigned long t;
    t=(x^(x<<11));x=y;y=z;z=w; return( w=(w^(w>>19))^(t^(t>>8)) );
}

class Dice
{
public:
    vector<int> pip; // 東南西北上下の目
    Dice(){
        pip.assign(6, -1);
    }
    void roll(int d){ // 東南西北右左に回転
        int dir[][4] = {{4,2,5,0},{4,3,5,1},{4,0,5,2},{4,1,5,3},{0,3,2,1},{0,1,2,3}};
        int tmp = pip[dir[d][0]];
        for(int i=0; i<3; ++i)
            pip[dir[d][i]] = pip[dir[d][i+1]];
        pip[dir[d][3]] = tmp;
    }
    bool operator==(const Dice& d) const{
        return pip == d.pip;
    }
};

class Data
{
public:
    int y, x;
    Dice d;
    Data(int y0, int x0, const Dice& d0){
        y = y0;
        x = x0;
        d = d0;
    }
    int toInt(){
        return ((y * 14 + x) * 6 + d.pip[4]) * 6 + d.pip[0];
    }
};

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

int main()
{
    int h, w;
    cin >> h >> w;

    vector<string> s(h+2, string(w+2, '.'));
    for(int i=1; i<=h; ++i){
        for(int j=1; j<=w; ++j){
            cin >> s[i][j];
        }
    }
    h += 2;
    w += 2;

    vector<string> face(6);
    for(int i=0; i<6; ++i)
        cin >> face[i];

    int sy, sx, gy, gx;
    cin >> sy >> sx >> gy >> gx;

    Dice gd;
    gd.pip[0] = 4;
    gd.pip[1] = 3;
    gd.pip[2] = 2;
    gd.pip[3] = 1;
    gd.pip[4] = 0;
    gd.pip[5] = 5;

    vector<string> dp(14*14*6*6, "no");
    multimap<string, Data> mm;
    for(int i=0; i<24; ++i){
        gd.roll(xor128() % 4);
        Data d(gy, gx, gd);
        if(dp[d.toInt()] == "no"){
            dp[d.toInt()] = face[gd.pip[4]];
            mm.insert(make_pair(face[gd.pip[4]], d));
        }else{
            -- i;
        }
    }

    while(!mm.empty()){
        string t0 = mm.begin()->first;
        Data d0 = mm.begin()->second;
        int y0 = d0.y;
        int x0 = d0.x;
        Dice dice0 = d0.d;
        mm.erase(mm.begin());
        if(t0 > dp[d0.toInt()])
            continue;
        if(t0.size() > 4000)
            continue;

        for(int i=0; i<4; ++i){
            int y = y0 + dy[i];
            int x = x0 + dx[i];
            if(s[y][x] != '+'){
                if(i == 0 && s[y][x] != '-' && s[y][x] != '<')
                    continue;
                if(i == 1 && s[y][x] != '|' && s[y][x] != '^')
                    continue;
                if(i == 2 && s[y][x] != '-' && s[y][x] != '>')
                    continue;
                if(i == 3 && s[y][x] != '|' && s[y][x] != 'v')
                    continue;
            }

            Dice dice = dice0;
            dice.roll(i);
            Data d(y, x, dice);
            string t = face[dice.pip[4]] + t0;

            if(t < dp[d.toInt()]){
                if(y == 1 && x == 3 && dice.pip[4] == 0)
                    y = 1;
                dp[d.toInt()] = t;
                mm.insert(make_pair(t, d));
            }
        }
    }

    string ret = dp[((sy * 14 + sx) * 6 + 0) * 6 + 4];
    if(ret.size() > 2000)
        cout << "infinite" << endl;
    else
        cout << ret << endl;

    return 0;
}
accuracy: 0.2676056338028169
time_ms: 40
memory_kb: 7216
final_rank: 13

code_snippet: #include <cstdio>
#include <iostream>
#include <sstream>
#include <iomanip>
#include <algorithm>
#include <cmath>
#include <string>
#include <vector>
#include <list>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <bitset>
#include <numeric>
#include <climits>
#include <cfloat>
using namespace std;

unsigned long xor128(){
    static unsigned long x=123456789,y=362436069,z=521288629,w=88675123;
    unsigned long t;
    t=(x^(x<<11));x=y;y=z;z=w; return( w=(w^(w>>19))^(t^(t>>8)) );
}

class Dice
{
public:
    vector<int> pip; // 東南西北上下の目
    Dice(){
        pip.assign(6, -1);
    }
    void roll(int d){ // 東南西北右左に回転
        int dir[][4] = {{4,2,5,0},{4,3,5,1},{4,0,5,2},{4,1,5,3},{0,3,2,1},{0,1,2,3}};
        int tmp = pip[dir[d][0]];
        for(int i=0; i<3; ++i)
            pip[dir[d][i]] = pip[dir[d][i+1]];
        pip[dir[d][3]] = tmp;
    }
    bool operator==(const Dice& d) const{
        return pip == d.pip;
    }
};

class Data
{
public:
    int y, x;
    Dice d;
    Data(int y0, int x0, const Dice& d0){
        y = y0;
        x = x0;
        d = d0;
    }
    int toInt(){
        return ((y * 14 + x) * 6 + d.pip[4]) * 6 + d.pip[0];
    }
};

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

int main()
{
    int h, w;
    cin >> h >> w;

    vector<string> s(h+2, string(w+2, '.'));
    for(int i=1; i<=h; ++i){
        for(int j=1; j<=w; ++j){
            cin >> s[i][j];
        }
    }
    h += 2;
    w += 2;

    vector<string> face(6);
    for(int i=0; i<6; ++i)
        cin >> face[i];

    int sy, sx, gy, gx;
    cin >> sy >> sx >> gy >> gx;

    Dice gd;
    gd.pip[0] = 4;
    gd.pip[1] = 3;
    gd.pip[2] = 2;
    gd.pip[3] = 1;
    gd.pip[4] = 0;
    gd.pip[5] = 5;

    vector<string> dp(14*14*6*6, "no");
    multimap<string, Data> mm;
    for(int i=0; i<24; ++i){
        gd.roll(xor128() % 4);
        Data d(gy, gx, gd);
        if(dp[d.toInt()] == "no"){
            dp[d.toInt()] = face[gd.pip[4]];
            mm.insert(make_pair(face[gd.pip[4]], d));
        }else{
            -- i;
        }
    }

    while(!mm.empty()){
        string t0 = mm.begin()->first;
        Data d0 = mm.begin()->second;
        int y0 = d0.y;
        int x0 = d0.x;
        Dice dice0 = d0.d;
        mm.erase(mm.begin());
        if(t0 > dp[d0.toInt()])
            continue;
        if(t0.size() > 2000)
            continue;

        for(int i=0; i<4; ++i){
            int y = y0 + dy[i];
            int x = x0 + dx[i];
            if(s[y][x] != '+'){
                if(i == 0 && s[y][x] != '-' && s[y][x] != '<')
                    continue;
                if(i == 1 && s[y][x] != '|' && s[y][x] != '^')
                    continue;
                if(i == 2 && s[y][x] != '-' && s[y][x] != '>')
                    continue;
                if(i == 3 && s[y][x] != '|' && s[y][x] != 'v')
                    continue;
            }

            Dice dice = dice0;
            dice.roll(i);
            Data d(y, x, dice);
            string t = face[dice.pip[4]] + t0;

            if(t < dp[d.toInt()]){
                if(y == 1 && x == 3 && dice.pip[4] == 0)
                    y = 1;
                dp[d.toInt()] = t;
                mm.insert(make_pair(t, d));
            }
        }
    }

    string ret = dp[((sy * 14 + sx) * 6 + 0) * 6 + 4];
    if(ret.size() > 1900)
        cout << "infinite" << endl;
    else
        cout << ret << endl;

    return 0;
}
accuracy: 0.2676056338028169
time_ms: 20
memory_kb: 4836
final_rank: 11

code_snippet: #include <cstdio>
#include <iostream>
#include <sstream>
#include <iomanip>
#include <algorithm>
#include <cmath>
#include <string>
#include <vector>
#include <list>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <bitset>
#include <numeric>
#include <climits>
#include <cfloat>
using namespace std;

unsigned long xor128(){
    static unsigned long x=123456789,y=362436069,z=521288629,w=88675123;
    unsigned long t;
    t=(x^(x<<11));x=y;y=z;z=w; return( w=(w^(w>>19))^(t^(t>>8)) );
}

class Dice
{
public:
    vector<int> pip; // 東南西北上下の目
    Dice(){
        pip.assign(6, -1);
    }
    void roll(int d){ // 東南西北右左に回転
        int dir[][4] = {{4,2,5,0},{4,3,5,1},{4,0,5,2},{4,1,5,3},{0,3,2,1},{0,1,2,3}};
        int tmp = pip[dir[d][0]];
        for(int i=0; i<3; ++i)
            pip[dir[d][i]] = pip[dir[d][i+1]];
        pip[dir[d][3]] = tmp;
    }
    bool operator==(const Dice& d) const{
        return pip == d.pip;
    }
};

class Data
{
public:
    int y, x;
    Dice d;
    Data(int y0, int x0, const Dice& d0){
        y = y0;
        x = x0;
        d = d0;
    }
    int toInt(){
        return ((y * 14 + x) * 6 + d.pip[4]) * 6 + d.pip[0];
    }
};

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

int main()
{
    int h, w;
    cin >> h >> w;

    vector<string> s(h+2, string(w+2, '.'));
    for(int i=1; i<=h; ++i){
        for(int j=1; j<=w; ++j){
            cin >> s[i][j];
        }
    }
    h += 2;
    w += 2;

    vector<string> face(6);
    for(int i=0; i<6; ++i)
        cin >> face[i];

    int sy, sx, gy, gx;
    cin >> sy >> sx >> gy >> gx;

    Dice gd;
    gd.pip[0] = 4;
    gd.pip[1] = 3;
    gd.pip[2] = 2;
    gd.pip[3] = 1;
    gd.pip[4] = 0;
    gd.pip[5] = 5;

    vector<string> dp(14*14*6*6, "no");
    multimap<string, Data> mm;
    for(int i=0; i<24; ++i){
        gd.roll(xor128() % 4);
        Data d(gy, gx, gd);
        if(dp[d.toInt()] == "no"){
            dp[d.toInt()] = face[gd.pip[4]];
            mm.insert(make_pair(face[gd.pip[4]], d));
        }else{
            -- i;
        }
    }

    while(!mm.empty()){
        string t0 = mm.begin()->first;
        Data d0 = mm.begin()->second;
        int y0 = d0.y;
        int x0 = d0.x;
        Dice dice0 = d0.d;
        mm.erase(mm.begin());
        if(t0 > dp[d0.toInt()])
            continue;
        if(t0.size() > 2000)
            continue;

        for(int i=0; i<4; ++i){
            int y = y0 + dy[i];
            int x = x0 + dx[i];
            if(s[y][x] != '+'){
                if(i == 0 && s[y][x] != '-' && s[y][x] != '<')
                    continue;
                if(i == 1 && s[y][x] != '|' && s[y][x] != '^')
                    continue;
                if(i == 2 && s[y][x] != '-' && s[y][x] != '>')
                    continue;
                if(i == 3 && s[y][x] != '|' && s[y][x] != 'v')
                    continue;
            }

            Dice dice = dice0;
            dice.roll(i);
            Data d(y, x, dice);
            string t = face[dice.pip[4]] + t0;

            if(t < dp[d.toInt()]){
                if(y == 1 && x == 3 && dice.pip[4] == 0)
                    y = 1;
                dp[d.toInt()] = t;
                mm.insert(make_pair(t, d));
            }
        }
    }

    string ret = dp[((sy * 14 + sx) * 6 + 0) * 6 + 4];
    if(ret.size() > 2000)
        cout << "infinite" << endl;
    else
        cout << ret << endl;

    return 0;
}
accuracy: 0.2676056338028169
time_ms: 20
memory_kb: 4832
final_rank: 10

code_snippet: #include <cstdio>
#include <iostream>
#include <sstream>
#include <iomanip>
#include <algorithm>
#include <cmath>
#include <string>
#include <vector>
#include <list>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <bitset>
#include <numeric>
#include <climits>
#include <cfloat>
using namespace std;

unsigned long xor128(){
    static unsigned long x=123456789,y=362436069,z=521288629,w=88675123;
    unsigned long t;
    t=(x^(x<<11));x=y;y=z;z=w; return( w=(w^(w>>19))^(t^(t>>8)) );
}

class Dice
{
public:
    vector<int> pip; // 東南西北上下の目
    Dice(){
        pip.assign(6, -1);
    }
    void roll(int d){ // 東南西北右左に回転
        int dir[][4] = {{4,2,5,0},{4,3,5,1},{4,0,5,2},{4,1,5,3},{0,3,2,1},{0,1,2,3}};
        int tmp = pip[dir[d][0]];
        for(int i=0; i<3; ++i)
            pip[dir[d][i]] = pip[dir[d][i+1]];
        pip[dir[d][3]] = tmp;
    }
    bool operator==(const Dice& d) const{
        return pip == d.pip;
    }
};

class Data
{
public:
    int y, x;
    Dice d;
    Data(int y0, int x0, const Dice& d0){
        y = y0;
        x = x0;
        d = d0;
    }
    int toInt(){
        return ((y * 14 + x) * 6 + d.pip[4]) * 6 + d.pip[0];
    }
};

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

int main()
{
    int h, w;
    cin >> h >> w;

    vector<string> s(h+2, string(w+2, '.'));
    for(int i=1; i<=h; ++i){
        for(int j=1; j<=w; ++j){
            cin >> s[i][j];
        }
    }
    h += 2;
    w += 2;

    vector<string> face(6);
    for(int i=0; i<6; ++i)
        cin >> face[i];

    int sy, sx, gy, gx;
    cin >> sy >> sx >> gy >> gx;

    Dice gd;
    gd.pip[0] = 4;
    gd.pip[1] = 3;
    gd.pip[2] = 2;
    gd.pip[3] = 1;
    gd.pip[4] = 0;
    gd.pip[5] = 5;

    vector<string> dp(14*14*6*6, "no");
    multimap<string, Data> mm;
    for(int i=0; i<24; ++i){
        gd.roll(xor128() % 4);
        Data d(gy, gx, gd);
        if(dp[d.toInt()] == "no"){
            dp[d.toInt()] = face[gd.pip[4]];
            mm.insert(make_pair(face[gd.pip[4]], d));
        }else{
            -- i;
        }
    }

    while(!mm.empty()){
        string t0 = mm.begin()->first;
        Data d0 = mm.begin()->second;
        int y0 = d0.y;
        int x0 = d0.x;
        Dice dice0 = d0.d;
        mm.erase(mm.begin());
        if(t0 > dp[d0.toInt()])
            continue;
        if(t0.size() > 2000)
            continue;

        for(int i=0; i<4; ++i){
            int y = y0 + dy[i];
            int x = x0 + dx[i];
            if(s[y][x] != '+'){
                if(i == 0 && s[y][x] != '-' && s[y][x] != '<')
                    continue;
                if(i == 1 && s[y][x] != '|' && s[y][x] != '^')
                    continue;
                if(i == 2 && s[y][x] != '-' && s[y][x] != '>')
                    continue;
                if(i == 3 && s[y][x] != '|' && s[y][x] != 'v')
                    continue;
            }

            Dice dice = dice0;
            dice.roll(i);
            Data d(y, x, dice);
            string t = face[dice.pip[4]] + t0;

            if(t < dp[d.toInt()]){
                if(y == 1 && x == 3 && dice.pip[4] == 0)
                    y = 1;
                dp[d.toInt()] = t;
                mm.insert(make_pair(t, d));
            }
        }
    }

    string ret = dp[((sy * 14 + sx) * 6 + 0) * 6 + 4];
    if(ret.size() > 2000)
        cout << "inifinity" << endl;
    else
        cout << ret << endl;

    return 0;
}
accuracy: 0.014084507042253521
time_ms: 20
memory_kb: 1380
final_rank: 15

code_snippet: #include <iostream>
#include <algorithm>
using namespace std;
 

// If this structure is used for two-dimensional surface,
// it assumes that the face id[0] faces the positive direction of the Y axis,
// the face id[1] faces the positive direction of the X axis
// and id[2] is top of the dice.
struct Dice {
  int id[6], cnt;
  const static int f[3][3];

  Dice() { init(); }

  void init() {
    for(int i = 0; i < 6; ++i) {
      id[i] = i;
    }
    cnt = 0;
  }

  // type (0:spin, 1:rollX, 2:rollY)
  // dir 1( ccw     neg      pos   )
  //    -1( cw      pos      neg   )
  void rotate(int type, int dir = 1) {
    const int *v = f[type];
    int a,b,c,t; a=v[0]; b=v[1]; c=v[2]; t=id[type];
    if(dir < 0) swap(a,c);
    id[type]=id[a]; id[a]=id[b]; id[b]=id[c]; id[c]=t;
  }

  bool next() {
    ++cnt;
    if(cnt == 24) {
      rotate(0,-1);
      rotate(1,-1);
      cnt = 0;
      return false;
    }
    if(cnt == 4*3) {
      rotate(2,-1);
      rotate(0,-1);
    } else if(cnt%4 == 0) {
      rotate(2);
    } else {
      rotate(0);
    }
    return true;
  }

  void roll(int dir) {
    //const static int dx[] = {1,0,-1,0};
    //const static int dy[] = {0,1,0,-1};
    switch(dir) {
      case 0: rotate(1,-1); break;
      case 1: rotate(2, 1); break;
      case 2: rotate(1, 1); break;
      case 3: rotate(2,-1); break;
    }
  }

  bool operator < (const Dice &d) const {
    for(int i = 0; i < 3; ++i)
      if(id[i] != d.id[i]) return id[i] < d.id[i];
    return false;
  }

  void show() {
    cout << id[4] << " / \\ " << id[5] << endl;
    cout << " /   \\" << endl;
    cout << "|\\ " << id[2] << " /|" << endl;
    cout << "|" << id[0] << "\\ /" << id[1] << "|" << endl;
    cout << " \\ | /" << endl;
    cout << "  \\|/" << endl;
    cout << "   " << id[3] << endl;
  }
};
const int Dice::f[3][3] = {{4,5,1},{3,4,2},{5,3,0}};

//----------------------------------------------------------

#include <map>
#include <vector>
#include <queue>
#include <set>
#include <string>

struct State {
  int i, j;
  Dice dice;

  State() {}
  State(int i, int j, Dice dice)
    : i(i), j(j), dice(dice) {}

  bool operator < (const State &s) const {
    if(i != s.i) return i < s.i;
    if(j != s.j) return j < s.j;
    return dice < s.dice;
  }
};

struct State2 : public State {
  int p;
  State2() {}
  State2(int i, int j, Dice dice, int p)
    : State(i,j,dice), p(p) {}

  bool operator < (const State2 &s) const {
    if(p != s.p) return p < s.p;
    return (State)(*this) < (State)s;
  }
};

const int di[] = {0,1,0,-1};  
const int dj[] = {1,0,-1,0};
const int MAX_H = 13;
const int MAX_W = 13;
const int STATE_NUM = 5000;

int H, W;
int G[MAX_H][MAX_W];
string F[6];
int si, sj, gi, gj;
map<State, int> id;
map<int, State> rid;

vector<int> E[STATE_NUM];

int getId(const State &s) {
  if(!id.count(s)) id[s] = (int)id.size()-1;
  rid[id[s]] = s;
  return id[s];
}

void init() {
  for(int i = 0; i < MAX_H; ++i) {
    for(int j = 0; j < MAX_W; ++j) {
      Dice dice;
      do {
        getId(State(i,j,dice));
      } while(dice.next());
    }
  }
}

void make() {
  for(int i = 0; i < STATE_NUM; ++i) E[i].clear();
  for(int i = 0; i < H; ++i) {
    for(int j = 0; j < W; ++j) {
      Dice dice;
      do {
        State s(i,j,dice);
        for(int d = 0; d < 4; ++d) {
          if(G[i][j] & (1<<d)) ; else continue;
          int ni = i + di[d];
          int nj = j + dj[d];
          if(ni < 0 || ni >= H) continue;
          if(nj < 0 || nj >= W) continue;
          Dice ndice = dice;
          ndice.roll(d);
          State t(ni,nj,ndice);
          E[id[s]].push_back(id[t]);
        }
      } while(dice.next());
    }
  }
}

bool bfs(int si, int sj, int gi, int gj) {
  queue<State> que;
  set<State> vis;
  State s(si,sj,Dice());
  que.push(s);
  vis.insert(s);
  while(!que.empty()) {
    s = que.front();
    que.pop();
    int sid = id[s];
    for(int i = 0; i < E[sid].size(); ++i) {
      State t = rid[E[sid][i]];
      if(vis.count(t)) continue;
      if(t.i == gi && t.j == gj) return true;
      que.push(t);
      vis.insert(t);
    }
  }
  return false;
}

int main() {
  init();
  while(cin >> H >> W) {
    for(int i = 0; i < H; ++i) {
      for(int j = 0; j < W; ++j) {
        char c;
        cin >> c;
        int &g = G[i][j];
        switch(c) {
          case '+': g = (1<<4)-1; break;
          case '|': g = (1<<1)|(1<<3); break;
          case '-': g = (1<<0)|(1<<2); break;
          case '<': g = (1<<2); break;
          case '>': g = (1<<0); break;
          case '^': g = (1<<3); break;
          case 'v': g = (1<<1); break;
          case '.': g = 0; break;
        }
      }
    }
    cin >> F[2];
    cin >> F[5];
    cin >> F[4];
    cin >> F[0];
    cin >> F[1];
    cin >> F[3];
    cin >> si >> sj;
    cin >> gi >> gj;
    --si; --sj; --gi; --gj;
    make();

    set<State2> vis[2];
    string res;

    {
      Dice dice;
      do {
        if(dice.id[0] == 4-1 &&
           dice.id[1] == 5-1 &&
           dice.id[2] == 1-1) {
          break;
        }
      } while(dice.next());
      State s(si,sj,dice);
      vis[0].insert(State2(si,sj,dice,0));
      res = "";
    }

    if(!bfs(si,sj,gi,gj)) {
      cout << "no" << endl;
      continue;
    }
    for(int t = 0; ; t = 1-t) {
      int n = 1-t;
      char mini = 127;

      for(set<State2>::iterator it = vis[t].begin();
          it != vis[t].end(); ++it) {
        if(it->i == gi && it->j == gj &&
           it->p == F[it->dice.id[2]].size()) {
          res += '$';
          break;
        }

        if(it->p == F[it->dice.id[2]].size()) {
          int sid = id[*it];
          for(int i = 0; i < E[sid].size(); ++i) {
            State t = rid[E[sid][i]];
            if(F[t.dice.id[2]][0] <= mini) {
              if(F[t.dice.id[2]][0] < mini) {
                vis[n].clear();
                mini = F[t.dice.id[2]][0];
              }
              vis[n].insert(State2(t.i, t.j, t.dice, 1));
            }
          }
        } else {
          if(F[it->dice.id[2]][it->p] <= mini) {
            if(F[it->dice.id[2]][it->p] < mini) {
              vis[n].clear();
              mini = F[it->dice.id[2]][it->p];
            }
            State2 tmp = *it;
            ++tmp.p;
            vis[n].insert(tmp); 
          }
        }
      }

      if(*res.rbegin() == '$') {
        res = res.substr(0, (int)res.size()-1);
        break;
      }
      if(mini == 127) {
        res = "no";
        break;
      }
      if(res.size() > STATE_NUM*13) {
        res = "infinite";
        break;
      }
      res += mini;
    }
    cout << res << endl;
  }
  return 0;
}
accuracy: 0.5915492957746479
time_ms: 1360
memory_kb: 4664
final_rank: 7