Mistwald(ZOJ 3497)
Problem Description
In chapter 4 of the game Trails in the Sky SC, Estelle Bright and her friends are crossing Mistwald to meet their final enemy, Lucciola.Mistwald is a mysterious place. It consists of M * N scenes, named Scene (1, 1) to Scene (M, N). Estelle Bright and her friends are initially at Scene (1, 1), the entering scene. They should leave Mistwald from Scene (M, N), the exiting scene. Note that once they reach the exiting scene, they leave Mistwald and cannot come back. A scene in Mistwald has four exits, north, west, south, and east ones. These exits are controlled by Lucciola. They may not lead to adjacent scenes. However, an exit can and must lead to one scene in Mistwald.

Now you are competing with your roommate for who uses less time to leave Mistwald. Your roommate says that he only uses P seconds. It is known that he lies from time to time. Thus, you may want to code and find out whether it is a lie.
Input
There are multiple test cases. The first line of input is an integer T ≈ 10 indicating the number of test cases.Each test case begins with a line of two integers M and N (1 ≤ M, N ≤ 5), separated by a single space, indicating the size of Mistwald. In the next M lines, the ith line contains N pieces of scene information, separated by spaces, describing Scene (i, 1) to Scene (i, N). A scene description has the form "((x1,y1),(x2,y2),(x3,y3),(x4,y4))" (1 ≤ xk ≤ M; 1 ≤ yk ≤ N; 1 ≤ k ≤ 4) indicating the locations of new scenes the four exits lead to. The following line contains an integer Q (1 ≤ Q ≤ 100). In the next Q lines, each line contains an integer P (0 ≤ P ≤ 100,000,000), which is the time your roommate tells you.
Test cases are separated by a blank line.
Output
For each P, output one of the following strings in one line: "True" if it cannot be a lie; "Maybe" if it can be a lie; "False" if it must be a lie. Print a blank line after each case.Sample Input
2 3 2 ((3,1),(3,2),(1,2),(2,1)) ((3,1),(3,1),(3,1),(3,1)) ((2,1),(2,1),(2,1),(2,2)) ((3,2),(3,2),(3,2),(3,2)) ((3,1),(3,1),(3,1),(3,1)) ((3,2),(3,2),(3,2),(1,1)) 3 1 2 10 2 1 ((2,1),(2,1),(2,1),(2,1)) ((2,1),(2,1),(2,1),(2,1)) 2 1 2
Sample Output
Maybe False Maybe True False
My Code
这种类型的题我也是第一次遇到,其实就是利用邻接矩阵的幂的知识,关于邻接矩阵的幂大家可以看下这篇《有向图邻接矩阵幂的意义》,这道题其实就是问长度为p的路径是不是只能到终点。
#include
#include
#include
using namespace std;
int t;
int x[5], y[5];
struct Matrix
{
int M[30][30];
};
Matrix mul(Matrix m1, Matrix m2, int n)
{
Matrix m3;
memset(m3.M, 0, sizeof(m3.M));
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
{
for (int k = 0; k < n; k++)
m3.M[i][j] += (m1.M[i][k] * m2.M[k][j]);
}
return m3;
}
Matrix pow(Matrix m, int k, int n)
{
Matrix ans;
memset(ans.M, 0, sizeof(ans.M));
for (int i = 0; i < n; i++)
ans.M[i][i] = 1;
while (k)
{
if (k & 1)
ans = mul(ans, m, n);
m = mul(m, m, n);
k >>= 1;
}
return ans;
}
void print(Matrix res, int nm)
{
if (!res.M[0][nm - 1]) //没有长度为p的到终点的路径输出false
{
printf("False
");
return;
}
for (int i = 1; i < nm - 1; i++)
if (res.M[0][i]) //除到终点外还有到其他场景的长度为p的路径输出maybe
{
printf("Maybe
");
return;
}
printf("True
"); //只有一条长度为p的路径且到终点,输出true
}
int main()
{
int n, m;
Matrix ans;
cin >> t;
while (t--)
{
scanf("%d%d", &n, &m);
getchar();
memset(ans.M, 0, sizeof(ans.M));
for (int i = 0; i < n; i++)
for (int j = 0; j < m; j++)
{
scanf("((%d,%d),(%d,%d),(%d,%d),(%d,%d))", &x[0], &y[0], &x[1], &y[1], &x[2], &y[2], &x[3], &y[3]);
getchar();
if (i == n - 1 && j == m - 1) //到了终点就会立马离开,所以终点不需要出口
continue;
int u = i * m + j;
for (int k = 0; k < 4; k++)
{
int v = m * (x[k] - 1) + y[k] - 1;
ans.M[u][v] = 1; //建立邻接矩阵
}
}
int q;
scanf("%d", &q);
while (q--)
{
int p;
int nm = n * m;
scanf("%d", &p);
Matrix res = pow(ans, p, nm); //邻接矩阵的p次方就是长度为p的路径
print(res, nm);
}
printf("
");
}
return 0;
}