zoj 3497 Mistwald 矩阵快速幂

Mistwald Time Limit: 2 Seconds       Memory Limit: 65536 KB

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.

zoj 3497 Mistwald 矩阵快速幂_第1张图片

Estelle Bright and her friends walk very fast. It only takes them 1 second to cross an exit, leaving a scene and entering a new scene. Other time such as staying and resting can be ignored. It is obvious that the quicker they leave Mistwald, the better.

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 Npieces 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


题意:给你一个n*m矩阵,每个点有四个方向可以走。室友说自己用p步走到了终点,问是一定还是可能,还是不可能。

做法:把每个点化做一数,i行j列为(i*m+j)。 然后把每个点的转移写在构造矩阵中,比如第二个案例,就只用建一条边,0->1,所以mp.a[0][1]=1。
如果到了终点,就不再走了,所以构造矩阵第一维不能是终点数字。然后p次快速幂,结果的第一行,为p步能到达的点。如果快速幂后,[0][n*m-1]不为1,那就是false。
如果为1,判断第一行其他点是否为1,如果有为1的,那么他就是可能撒谎,他可能第p步没到达终点,而是到了其他点。否者就是true。

给个案例
2
3 2
((1,2),(1,2),(2,1),(2,1)) ((3,2),(3,2),(3,2),(3,2))
((3,1),(3,1),(3,1),(3,1)) ((2,1),(2,1),(2,1),(2,1))
((3,2),(3,2),(3,2),(3,2)) ((2,1),(2,1),(2,1),(2,1))
9
5
False
1
False
2
Maybe
3
True
一共只有两条路可以到达终点,分别要2步或者3步,如果室友说用了三步,那么肯定是对的,如果他用个两步,是不会撒谎把自己说的慢了。如果说两步,那可能是撒谎了,他可能是用了三步走才走到的,两步的时候他在其他点。

#include<stdio.h>
#include<string.h>
#define Matr 50  
#define ll int
struct mat 
{
    ll a[Matr][Matr];
    mat() 
    {
        memset(a,0,sizeof(a));
    }
};
int Size;

mat multi(mat m1,mat m2)
{
    mat ans=mat(); 
    for(int i=0;i<Size;i++)
        for(int j=0;j<Size;j++)
            if(m1.a[i][j])//?????? 
                for(int k=0;k<Size;k++)
				{
					if((ans.a[i][k]+m1.a[i][j]*m2.a[j][k]))
                    ans.a[i][k]=1; 
				}
	return ans;
}
 
mat quickmulti(mat m,ll n)
{
    mat ans=mat();
    int i;
    for(i=0;i<Size;i++)
		ans.a[i][i]=1;
    while(n)
    {
        if(n&1) ans=multi(m,ans);
        m=multi(m,m);
        n>>=1;
    }
    return ans;
}

int main()
{
	int i,j,k;
	int t,n,m;
	char op;
	mat chu;
	mat mp;
	scanf("%d",&t);
	while(t--){
		scanf("%d %d",&n,&m); 
		mp=mat();
		Size=n*m;
		for(i=0;i<n;i++)
		{
			for(j=0;j<m;j++)
			{
				int x,y,s;
				s=i*m+j;
				getchar();
				scanf("%c",&op);
				for(k=0;k<4;k++)
				{
					scanf("%c",&op);
					scanf("%d,%d%c%c",&x,&y,&op,&op);
					x--,y--;
					int a;
					a=x*m+y;
					if(s!=n*m-1)
					mp.a[s][a]=1;
				}
			}
		}  
		int q,p;
		scanf("%d",&q); 
		while(q--){
			scanf("%d",&p);
			chu=mat(); 
			chu.a[0][0]=1; 
			chu=multi(chu,quickmulti(mp,p));

			if(chu.a[0][n*m-1]==0)
				printf("False\n");
			else
			{
				int flag=0;
				for(int i=0;i<n*m-1;i++)
				{
					if(chu.a[0][i])
						flag=1;
				}
				if(flag)
					printf("Maybe\n");
				else
					printf("True\n"); 
			}
		}
		printf("\n");
	}
	return 0;
}


你可能感兴趣的:(矩阵快速幂)