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 (MN). Estelle Bright and her friends are initially at Scene (1, 1), the entering scene. They should leave Mistwald from Scene
(MN), 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.

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 ≤ MN ≤ 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 (iN). 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;
}
时间: 2024-10-07 15:07:50

zoj 3497 Mistwald 矩阵快速幂的相关文章

ZOJ 3497 Mistwald 矩阵

利用可达矩阵的幂来判断是否可达 #include <cstdio> #include <cstring> #include <algorithm> #include <queue> #include <stack> #include <map> #include <set> #include <climits> #include <iostream> #include <string>

zoj 2853 Evolution 矩阵快速幂

在我的电脑上code::blocks运行过不了,但代码是可以AC的,很是郁闷. 问了大神,知道了函数的参数是放在栈区,结构体太大的话,栈就爆了,如是后来就听从大神的意见用引用改写了. 传送门:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=1853 #include <stdio.h> #include <string.h> #include <stdlib.h> int Len_Matrix; in

zoj 2974 Just Pour the Water矩阵快速幂

Just Pour the Water Time Limit: 2 Seconds      Memory Limit: 65536 KB Shirly is a very clever girl. Now she has two containers (A and B), each with some water. Every minute, she pours half of the water in A into B, and simultaneous pours half of the

zoj 2853 Evolution(矩阵快速幂)

Evolution is a long, long process with extreme complexity and involves many species. Dr. C. P. Lottery is currently investigating a simplified model of evolution: consider that we haveN (2 <= N <= 200) species in the whole process of evolution, inde

ZOJ 3690 &amp; HDU 3658 (矩阵快速幂+公式递推)

ZOJ 3690 题意: 有n个人和m个数和一个k,现在每个人可以选择一个数,如果相邻的两个人选择相同的数,那么这个数要大于k 求选择方案数. 思路: 打表推了很久的公式都没推出来什么可行解,好不容易有了想法结果WA到天荒地老也无法AC.. 于是学习了下正规的做法,恍然大悟. 这道题应该用递推 + 矩阵快速幂. 我们设F(n) = 有n个人,第n个人选择的数大于k的方案数: G(n) = 有n个人,第n个人选择的数小于等于k的方案数: 那么递推关系式即是: F(1)=m?k,G(1)=k F(n

ZOJ 2794 Just Pour the Water 【矩阵快速幂】

给你n个杯子,每次有特定的到水规则,倒m次请问最后每个被子里还有多少水 我们很容易发现每次变化的规则相同,那么可以set 一个矩阵存放 然后多次倒水就相当于矩阵相乘,在m 范围达到(1<= M <= 1,000,000,000) 的情况下使用矩阵快速幂再好不过 这到题目注意的一点是,得使用Double 变量,如果使用FLoat会导致Wrong Answer Source Code: //#pragma comment(linker, "/STACK:16777216") /

zoj 3538 Arrange the Schedule(矩阵快速幂)

Arrange the Schedule Time Limit: 1 Second      Memory Limit: 65536 KB In Summer 2011, the ZJU-ICPC Team has a n-days training schedule. ZJU-ICPC Team has been divided into 4 Group: Akiba, BiliBili, CIA, Double(Group A, B, C, D). There is a group in c

【ZOJ 2974】Just Pour the Water(矩阵快速幂)

传送门:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=2974 题意 给出n个杯子与初始水量同时进行操作 将其中的水同时平均分入所指定的杯子 进行x次后 输出杯子剩余水量 刚拿到这个题,第一反应是递推找规律,但是因为每个杯子的初始水量是未知的,所以能找的只是每个杯子水量与其余杯子水量的关系. 但是看到了操作次数巨大,而且最多只有20个杯子,感觉可以用快速幂去做. 我们假设矩阵a[i][j]代表第i个杯子的水有a[i][j

ZOJ 2105 Number Sequence(矩阵快速幂)

题意: f(1) = 1, f(2) = 1, f(n) = (A * f(n - 1) + B * f(n - 2)) mod 7. 给定A,B,求f(n). 法一: 网上较多的题解都提到了寻找1 1循环节的方法,的确非常巧妙,每位0~6,共7种可能,相邻两位共49种可能,因此循环周期至多为49,一旦出现相同数对,那么其后必相同.但是,该方法只是简单提及了49,却并没有证明1 1循环节一定存在,没有排除可能前面一段不循环,后面一段开始周期性循环的可能性.(是我悟性太差吗,为什么大多数题解都只谈