zoj 3497 Mistwald(矩阵快速幂)

来源:互联网 发布:手机屏幕变魔术的软件 编辑:程序博客网 时间:2024/06/14 08:20

#include <iostream>#include <cmath>#include <cstdio>#include <cstdlib>#include <cstring>#include <algorithm>#define inputt int t;cin>>t;#define pi acos(-1.0)#define lson o*2,l,m#define rson o*2+1,m+1,r#define Mid (l+r)/2#define MAXN 30typedef long long ll;using namespace std;typedef struct line{    int r[MAXN][MAXN];}line;line temp;int n, k, m;line matmult(line a, line b){    memset(temp.r, 0, sizeof(temp.r));    for(int i = 1; i <= n; i++)     for(int j = 1; j <= n; j++)      for(int k = 1; k <=n; k++)        temp.r[i][j]+=a.r[i][k]*b.r[k][j];    return temp;}line power(line a, line b, int k) {    for(; k; k /= 2) {        if(k & 1)b = matmult(a, b);        a = matmult(a, a);    }    return b;}int main() {    int t;    int N, M;    scanf("%d", &t);    line unit, start;    while(t--) {        memset(unit.r, 0, sizeof(unit.r));        memset(start.r, 0, sizeof(start.r));        scanf("%d%d", &N, &M);        getchar();        int T = N * M;        for(int i = 1; i <= T; i++) {            unit.r[i][i] = 1;        }        int x1, y1, x2, y2, x3, y3, x4, y4;        for(int i = 1; i <= N; i++)         for(int j = 1; j <= M; j++)         {                scanf("((%d,%d),(%d,%d),(%d,%d),(%d,%d))", &x1, &y1, &x2, &y2, &x3, &y3, &x4, &y4);                getchar();                if(i == N && j == M)                continue;                start.r[(i - 1)*M + j][(x1 - 1)*M + y1] = 1;                start.r[(i - 1)*M + j][(x2 - 1)*M + y2] = 1;                start.r[(i - 1)*M + j][(x3 - 1)*M + y3] = 1;                start.r[(i - 1)*M + j][(x4 - 1)*M + y4] = 1;            }        n = T;        int q, p;        scanf("%d", &q);        while(q--) {            scanf("%d", &p);            line ans = power(start, unit, p);            if(ans.r[1][T] == 0)                printf("False\n");            else {                int flag = 0;                for(int i = 1; i < T; i++)                 {                    if(ans.r[1][i])                    {                        flag = 1;                        break;                    }                }                if(!flag)                    printf("True\n");                else                    printf("Maybe\n");            }        }        printf("\n");    }    return 0;}



(start.r)12=1,表示能从1到2,(start.r)12=0表示不能从1到达2        

(start.r)ij=∑k (start.r)ik*(start.r)kj

只要有一个(start.r)ik*(start.r)kj=1,那么(start.r)ij大于0说明两步能从i到j,第一步能从i到k,第二步能从k到j

这样直接对原矩阵进行n次相乘,得到的新矩阵中还大于0的数就是n步都能到达的点

1 0
原创粉丝点击