//Wycieczka górska - 4C, PA 2020

#define _CRT_SECURE_NO_WARNINGS
#include <cstdio>
#include <climits>
#include <stdio.h>
#include <iostream>
#include <string.h>
#include <math.h>
#include <algorithm>
#include <vector>
#include <queue>
#include <map>

typedef long long lLong;
typedef unsigned long uLong;
typedef unsigned long long ulLong;
typedef unsigned int uInt;
typedef unsigned char Byte;

typedef std::vector<int> VI;

typedef std::vector<bool> VBit;
typedef std::vector<VBit> VVBit;

typedef std::vector<char> VC;
typedef std::vector<VC> VVC;

typedef std::pair<lLong, lLong> VPLL;
typedef std::vector<VPLL> VVPLL;

typedef std::pair<int, int> RowCol;
typedef std::queue<RowCol*> RowColQ;
typedef std::vector<RowCol*> RowColV;


typedef struct GoraDol
{
public:
	int Gora; //ile razy sciezka wymaga pojscia w gore
	int Dol; //ile razy sciezka wymaga pojscia w dol
} GoraDol;

using namespace std;

// tablice z kierunkami ruchow dla BFS
VI kierWie = { -1, 1, 0,  0 };
VI kierKol = {  0, 0, 1, -1 };

class PrzypadekTestowy
{
private:
	FILE* _input;
	int _n, _m;	
	RowColV _sciezka; //przebyta trasa oryginalna

	inline void WczytajTrojkeInt(int* v1, int *v2, int *v3)
	{
		auto _ = fscanf(_input, "%d %d %d", v1, v2, v3);
	}

	inline void WczytajChar(char* value)
	{
		auto _ = fscanf(_input, "%c", value);
	}
	inline void WczytajParelLong(lLong* v1, lLong *v2)
	{
		auto _ = fscanf(_input, "%lld %lld", v1, v2);
	}
	inline void WyczyscNewLine()
	{
		auto _ = fscanf(_input, "\n");
	}
	// zwraca liczbe sasiadow dodanych do kolejki
	inline int DodajSasiadow(VVC& mapa, RowCol &rc, RowColQ &q, VVBit& odwiedzone)
	{		
		int ileDodano = 0;
		for (int i = 0; i < 4; i++)
		{
			int sasiadWieIdx = rc.first + kierWie[i];
			int sasiadKolIdx = rc.second + kierKol[i];

			if (sasiadWieIdx < 0 || sasiadKolIdx < 0) continue;
			if (sasiadWieIdx >=_n || sasiadKolIdx >= _m) continue;
			if (odwiedzone[sasiadWieIdx][sasiadKolIdx]) continue;
			if (mapa[sasiadWieIdx][sasiadKolIdx] == 'X') continue;

			// sasiad prawidlowy - dorzuc do kolejki do sprawdzenia
			q.push(new RowCol(sasiadWieIdx, sasiadKolIdx));			
			odwiedzone[sasiadWieIdx][sasiadKolIdx] = true;
			ileDodano++;
		}
		return ileDodano;
	}
	inline void BFS(VVC& mapa)
	{		
		bool czyKoniec = false;		
		RowCol wStart = { 0,0 }, wKoniec = { _n-1,_m-1 }; // poczatek i koniec sciezki na mapie
		RowColQ q; //kolejka do przechowania sciezek do sprawdzenia

		VVBit odwiedzone = VVBit(_n, VBit(_m, false));
		int ileKrokow = 0, ileWezlowCur = 1, ileWezlowNext = 0;

		q.push(&wStart);
		
		odwiedzone[wStart.first][wStart.second] = true;

		while (!q.empty())
		{
			RowCol &rc = *q.front();
			q.pop();
			if (rc == wKoniec)
			{
				czyKoniec = true;
				_sciezka.push_back(new RowCol(rc));
				break;
			}
			
			int ileDodano =  DodajSasiadow(mapa, rc, q, odwiedzone);
			ileWezlowNext += ileDodano;
			
			//dodajemy do celow backtrackingu
			if (ileDodano > 0)
			{				
				_sciezka.push_back(new RowCol(rc));
			}
			ileWezlowCur--;
			if (ileWezlowCur == 0)
			{
				ileWezlowCur = ileWezlowNext;
				ileWezlowNext = 0;
				ileKrokow++;			
			}
		}
	}
	
	inline GoraDol WyznaczKierunki()
	{
		GoraDol result = {0,0};
		// na podstawie przetestowanej sciezki wyznacz kierunki ilosciowy (bactracking)
		RowCol* prev = NULL;
		for (auto k=_sciezka.rbegin();k!=_sciezka.rend();++k)
		{
			auto cur = *k;
			if (prev)
			{
				// jesli nie nalezy do najkrotszej sciezki powrotnej to zignoruj punkt
				if (prev->first != cur->first && prev->second != cur->second)
					continue;
				if (cur->first == prev->first) //przemieszczenie w poziomie
				{
					if (cur->second < prev->second)
						result.Gora++; //ruch w prawo oznacza ruch w dol
					else
						result.Dol++;
				}
				else
				{
					if (cur->first < prev->first)
						result.Gora++; //ruch w prawo oznacza ruch w dol
					else
						result.Dol++;
				}
			}
			prev = cur;
		}
		return result;
	}
public:	
	PrzypadekTestowy(FILE* input)
	{
		_input = input;
		_n = 0;
		_m = 0;
	}

	inline void Wykonaj()
	{
		int k;//mapa nxm, liczba wedrowcow

		WczytajTrojkeInt(&_n, &_m, &k);
		WyczyscNewLine();
			
		VVC mapa = VVC(_n, VC(_m, '.')); //rozmiar rowny liczbie mozliwych zabawek		
		VVPLL znajomi = VVPLL(k, { 0,0 });

		for (int i = 0; i < _n; i++)
		{
			for (int j = 0; j < _m; j++)
			{
				char c;
				WczytajChar(&c);
				if (c == 'X')
					mapa[i][j] = c;
			}
			WyczyscNewLine();
		}	

		for (int i = 0; i < k; i++)
		{
			auto z = &znajomi[i];
			WczytajParelLong(&z->first, &z->second);			
		}

		BFS(mapa);
		auto kierunki = WyznaczKierunki();
		std::map<lLong, int> wyniki;
		lLong czasMin = LLONG_MAX;
		// nalicz finalne czasy dla kierunkow
		for (auto &z: znajomi)
		{			
			lLong czas = z.first * kierunki.Gora + z.second * kierunki.Dol;
			wyniki[czas]++;
			if (czas < czasMin)
				czasMin = czas;
		}
		printf("%lld %d\n", czasMin,wyniki[czasMin]);
	}
};

int main(int argc, char** argv)
{
	FILE* in = stdin;
	if (argc > 1)
	{
		in = fopen(argv[1], "rt");
		if (NULL == in)
		{
			in = stdin;
		}
	}

	PrzypadekTestowy* p = new PrzypadekTestowy(in);
	p->Wykonaj();
	fflush(in);
	fclose(in);
	delete(p);
	return 0;
}
