Problem:
Problem G: Rolling Dice

The north country is conquered by the great shogun-sama (which means
king). Recently many beautiful dice which were made by order of the
great shogun-sama were given to all citizens of the country. All
citizens received the beautiful dice with a tear of delight. Now they
are enthusiastically playing a game with the dice.

The game is played on grid of h * w cells that each of which has a
number, which is designed by the great shogun-sama's noble philosophy.
A player put his die on a starting cell and move it to a destination
cell with rolling the die. After rolling the die once, he takes a
penalty which is multiple of the number written on current cell and
the number printed on a bottom face of the die, because of malicious
conspiracy of an enemy country. Since the great shogun-sama strongly
wishes, it is decided that the beautiful dice are initially put so
that 1 faces top, 2 faces south, and 3 faces east. You will find that
the number initially faces north is 5, as sum of numbers on opposite
faces of a die is always 7. Needless to say, idiots those who move his
die outside the grid are punished immediately.

The great shogun-sama is pleased if some citizens can move the
beautiful dice with the least penalty when a grid and a starting cell
and a destination cell is given. Other citizens should be sent to coal
mine (which may imply labor as slaves). Write a program so that
citizens can deal with the great shogun-sama's expectations.

Input

The first line of each data set has two numbers h and w, which stands
for the number of rows and columns of the grid.

Next h line has w integers, which stands for the number printed on the
grid. Top-left corner corresponds to northwest corner.

Row number and column number of the starting cell are given in the
following line, and those of the destination cell are given in the next
line. Rows and columns are numbered 0 to h-1, 0 to w-1, respectively.

Input terminates when h = w = 0.

Output

For each dataset, output the least penalty.

Constraints

1 ≤ h, w ≤ 10

0 ≤ number assinged to a cell ≤ 9

the start point and the goal point are different.

Sample Input

1 2
8 8
0 0
0 1
3 3
1 2 5
2 8 3
0 1 2
0 0
2 2
3 3
1 2 5
2 8 3
0 1 2
0 0
1 2
2 2
1 2
3 4
0 0
0 1
2 3
1 2 3
4 5 6
0 0
1 2
0 0

Output for the Sample Input

24
19
17
6
21

Solution in C# (judge verdict: Accepted)

using System;
using System.Collections;
using System.Collections.Generic;
 
class TEST{
	static void Main(){
		while(true){
			String s="";
			while(String.IsNullOrEmpty(s))s=Console.ReadLine();
			var d=Array.ConvertAll(s.Split(' '),e=>int.Parse(e));
			if(d[0]==0&&d[1]==0)break;
			Sol mySol =new Sol(d);
			mySol.Solve();
		}
	}
}

class Sol{
	public void Solve(){
		//ダイクストラ
		//　サイコロのエンコードがガバガバだが(Max:64*7+8*7+7=511)
		//  dp[H*W][enc(dice)]:最小コスト　を更新する
		
		int INF=(int)1e9;
		int dmax=64*7+8*7+7;
		int[][] dp=new int[H*W][];
		for(int i=0;i<H*W;i++){
			dp[i]=new int[dmax+1];
			for(int j=0;j<=dmax;j++)dp[i][j]=INF;
		}
		
		PriorityQueue<State> PQ=new PriorityQueue<State>();
		
		State Init=new State(0,Start[0]*W+Start[1],new Dice(1,7-2,3));
		dp[Init.V][Dice.Enc(Init.D)]=0;
		
		PQ.Push(Init);
		
		while(!PQ.IsEmpty){
			State state=PQ.Top;PQ.Pop();
			int C=state.C;
			int V=state.V;
			Dice D=state.D;
//Console.Write("pop:C={0},R={1},C={2},Dice:",C,V/W,V%W);
//Console.WriteLine(" T:{0},N:{1},E:{2},S:{3},W:{4},B:{5}",D.T,D.N,D.E,D.S,D.W,D.B);
			//左
			if(V%W!=0){
				if(dp[V-1][Dice.Enc(Dice.RotL(D))]>C+A[V/W][V%W-1]*Dice.RotL(D).B){
					dp[V-1][Dice.Enc(Dice.RotL(D))]=C+A[V/W][V%W-1]*Dice.RotL(D).B;
					PQ.Push(new State(dp[V-1][Dice.Enc(Dice.RotL(D))],V-1,Dice.RotL(D)));
				}
			}
			//右
			if(V%W!=W-1){
				if(dp[V+1][Dice.Enc(Dice.RotR(D))]>C+A[V/W][V%W+1]*Dice.RotR(D).B){
					dp[V+1][Dice.Enc(Dice.RotR(D))]=C+A[V/W][V%W+1]*Dice.RotR(D).B;
					PQ.Push(new State(dp[V+1][Dice.Enc(Dice.RotR(D))],V+1,Dice.RotR(D)));
				}
			}
			//下
			if(V/W!=H-1){
				if(dp[V+W][Dice.Enc(Dice.RotD(D))]>C+A[V/W+1][V%W]*Dice.RotD(D).B){
					dp[V+W][Dice.Enc(Dice.RotD(D))]=C+A[V/W+1][V%W]*Dice.RotD(D).B;
					PQ.Push(new State(dp[V+W][Dice.Enc(Dice.RotD(D))],V+W,Dice.RotD(D)));
				}
			}
			//上
			if(V/W!=0){
				if(dp[V-W][Dice.Enc(Dice.RotU(D))]>C+A[V/W-1][V%W]*Dice.RotU(D).B){
					dp[V-W][Dice.Enc(Dice.RotU(D))]=C+A[V/W-1][V%W]*Dice.RotU(D).B;
					PQ.Push(new State(dp[V-W][Dice.Enc(Dice.RotU(D))],V-W,Dice.RotU(D)));
				}
			}
		}
		
		
		
		int Min=INF;
		for(int i=0;i<=dmax;i++){
			Min=Math.Min(Min,dp[Goal[0]*W+Goal[1]][i]);
		}
		
		Console.WriteLine(Min);
		
		
		
	}
	
	class State:IComparable<State>{
		public int C;
		public int V;
		public Dice D;
		public State(int c_,int v_,Dice d_){
			C=c_;V=v_;D=d_;
		}
		public int CompareTo(State other){
			//比較を逆順にしておく
			return this.C>other.C?-1:this.C<other.C?1:0;
		}
	}
		
	
	
	
	
	int H;
	int W;
	int[][] A;
	int[] Start;
	int[] Goal;
	public Sol(int[] d_){
		H=d_[0];W=d_[1];
		A=new int[H][];
		for(int i=0;i<H;i++){
			A[i]=ria();
		}
		Start=ria();
		Goal=ria();
	}

	static String rs(){return Console.ReadLine();}
	static int ri(){return int.Parse(Console.ReadLine());}
	static long rl(){return long.Parse(Console.ReadLine());}
	static double rd(){return double.Parse(Console.ReadLine());}
	static String[] rsa(){return Console.ReadLine().Split(' ');}
	static int[] ria(){return Array.ConvertAll(Console.ReadLine().Split(' '),e=>int.Parse(e));}
	static long[] rla(){return Array.ConvertAll(Console.ReadLine().Split(' '),e=>long.Parse(e));}
	static double[] rda(){return Array.ConvertAll(Console.ReadLine().Split(' '),e=>double.Parse(e));}
}







class Dice{
	
	public int T;
	public int B;
	public int N;
	public int E;
	public int W;
	public int S;
	
	public Dice(int t_,int n_,int e_){
		T=t_;
		N=n_;
		B=7-T;
		S=7-N;
		E=e_;
		W=7-E;
	}

	public static int Enc(Dice D){
		return 64*D.T+8*D.N+D.E;
	}
	public static Dice Dec(int N){
		int top=N/64;
		int north=(N%64)/8;
		int east=N%8;
		return new Dice(top,north,east);
	}
	
	public static Dice RotR(Dice D){
		return new Dice(D.W,D.N,D.T);
	}
	public static Dice RotL(Dice D){
		return new Dice(D.E,D.N,D.B);
	}
	public static Dice RotU(Dice D){
		return new Dice(D.S,D.T,D.E);
	}
	public static Dice RotD(Dice D){
		return new Dice(D.N,D.B,D.E);
	}
}





class PriorityQueue<T> where T:IComparable<T>{

	//T:IComparable
	//IComparerかComparisonを指定してインスタンス化する事も可
	//引数なしインスタンス化⇒ComparedToで比較
	//大きいものほどTopへ

	enum typeCompare{
		isIComparerable=1,
		useIComparer=2,
		useDComparison=3
	}

	List<T> buffer;
	typeCompare tComp;
	IComparer<T> Cmper;
	Comparison<T> Cmp;
	
	public PriorityQueue(IComparer<T> comparer_){
		this.buffer=new List<T>();
		tComp=typeCompare.useIComparer;
		Cmper=comparer_;
		Cmp=null;
	}
	public PriorityQueue(){
		this.buffer=new List<T>();
		tComp=typeCompare.isIComparerable;
	}
	public PriorityQueue(Comparison<T> cmp_){
		this.buffer=new List<T>();
		tComp=typeCompare.useDComparison;
		Cmp=cmp_;
		Cmper=null;
	}
	public PriorityQueue(int capacity,IComparer<T> comparer_){
		this.buffer=new List<T>(capacity);
		tComp=typeCompare.useIComparer;
		Cmper=comparer_;
	}
	public PriorityQueue(int capacity){
		this.buffer=new List<T>(capacity);
		tComp=typeCompare.isIComparerable;
	}
	public PriorityQueue(int capacity,Comparison<T> cmp_){
		this.buffer=new List<T>(capacity);
		tComp=typeCompare.useDComparison;
		Cmp=cmp_;
	}
	

	void PushHeap(List<T> arr,T elem){
		int n=arr.Count;
		buffer.Add(elem);
		
		if(tComp==typeCompare.isIComparerable){
			try{
			while(n!=0){
				int i=(n-1)/2;
				if(arr[n].CompareTo(arr[i]) > 0){
					T tmp=arr[n];arr[n]=arr[i];arr[i]=tmp;
				}
				n=i;
			}
			}
		        catch (Exception e){
				Console.WriteLine("{0} Exception caught.", e);
		        }
		}else if(tComp==typeCompare.useIComparer){
			try{
			while(n!=0){
				int i=(n-1)/2;
				if(Cmper.Compare(arr[n],arr[i]) > 0){
					T tmp=arr[n];arr[n]=arr[i];arr[i]=tmp;
				}
				n=i;
			}
			}
		        catch (Exception e){
				Console.WriteLine("{0} Exception caught.", e);
		        }
		}else if(tComp==typeCompare.useDComparison){
			while(n!=0){
				int i=(n-1)/2;
				if(Cmp(arr[n],arr[i]) > 0){
					T tmp=arr[n];arr[n]=arr[i];arr[i]=tmp;
				}
				n=i;
			}
		}
	}
	
	void PopHeap(List<T> arr){
		int n=arr.Count - 1;
		arr[0] = arr[n];
		arr.RemoveAt(n);
		
		if(tComp==typeCompare.isIComparerable){
			for (int i=0,j;(j = 2*i +1)<n;){
				if((j!=n - 1)&&(arr[j].CompareTo(arr[j+1])<0))j++;
				if (arr[i].CompareTo(arr[j])<0){
					T tmp = arr[j]; arr[j] = arr[i]; arr[i] = tmp;
				}
				i=j;
			}
      		}else if(tComp==typeCompare.useIComparer){
			for (int i=0,j;(j = 2*i +1)<n;){
				if((j!=n - 1)&&(Cmper.Compare(arr[j],arr[j+1])<0))j++;
				if (Cmper.Compare(arr[i],arr[j])<0){
					T tmp = arr[j]; arr[j] = arr[i]; arr[i] = tmp;
				}
				i=j;
			}
		}else if(tComp==typeCompare.useDComparison){
			for (int i=0,j;(j = 2*i +1)<n;){
				if((j!=n - 1)&&(Cmp(arr[i],arr[j])<0))j++;
				if (Cmp(arr[i],arr[j])<0){
					T tmp = arr[j]; arr[j] = arr[i]; arr[i] = tmp;
				}
				i=j;
			}
		}
	}
	
	public void Push(T elem){
		PushHeap(this.buffer, elem);
	}
	
	public void Pop(){
		PopHeap(this.buffer);
	}
	
	public bool Contains(T elem){
		return this.buffer.Contains(elem);
	}
	public T Top{
		get{return this.buffer[0];}
	}
	
	public int Count{
		get{return this.buffer.Count;}
	}
	
	public T this[int i]{
		get{return this.buffer[i];}
	}
	public bool IsEmpty{
		get{return this.Count==0;}
	}
}