Mistwald(ZOJ3479)

原文链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3497

给出n*m个点,然后每个点会往其他的点移动,然后给定移动的方向点。求判断,在规定步数下,一定能到达终点输出true,不一定就maybe,否则就False。

把n*m个点离散化,然后给定的点到点就相当于在一个(n*m)*(n*m)的图中建立连接,然后对这个矩阵快速幂就是答案。需要注意的是,到达最后一个点的时候就不动了,所以最后一个点是不操作的。

#include<bits/stdc++.h>
using namespace std;
typedef vector<int> vec;
typedef vector<vec> mat;
int t,n,m,q;
#define mod 100007;
mat mul(mat a,mat b)//矩阵相乘
{
    mat c(a.size(),vec(b[0].size()));
    for(int i=0; i<a.size(); i++)
    {
        for(int k=0; k<b.size(); k++)
        {
            for(int j=0; j<b[0].size(); j++)
                c[i][j]=(c[i][j]+a[i][k]*b[k][j])%mod;
        }
    }
    return c;
}
mat solve_pow(mat a,int n)//快速幂
{
    mat b(a.size(),vec(a.size()));
    for(int i=0; i<a.size(); i++)
        b[i][i]=1;
    while(n>0)
    {
        if(n&1)
            b=mul(b,a);
        a=mul(a,a);
        n>>=1;
    }
    return b;
}
//--------------以上,快速幂模板-----------
int main()
{
    cin>>t;
    while(t--)
    {
        cin>>n>>m;
        getchar();
        mat G(30,vec(30));
        for(int i=1; i<=n; i++)//建图
        {
            for(int j=1; j<=m; j++)
            {
                int x1,y1,x2,y2,x3,y3,x4,y4;
                scanf("((%d,%d),(%d,%d),(%d,%d),(%d,%d))",&x1,&y1,&x2,&y2,&x3,&y3,&x4,&y4);
                getchar();
                //printf("((%d,%d),(%d,%d),(%d,%d),(%d,%d))\n",x1,y1,x2,y2,x3,y3,x4,y4);
                if((i-1)*m+j==n*m)
                    continue;
                G[(i-1)*m+j][(x1-1)*m+y1]=1;//这里涉及到离散化
                G[(i-1)*m+j][(x2-1)*m+y2]=1;
                G[(i-1)*m+j][(x3-1)*m+y3]=1;
                G[(i-1)*m+j][(x4-1)*m+y4]=1;
                //G[(i-1)*m+j][(i-1)*m+j]=1;
            }
        }

        cin>>q;
        while(q--)
        {
            int time;
            cin>>time;
            mat a=solve_pow(G,time);//快速幂运算
            if(a[1][n*m]==0)//如果终点是0就是到不了的
            {
                cout<<"False"<<endl;
                continue;
            }
            else
            {
                int flag=0;
                for(int i=1; i<n*m; i++)//如果仅有那个点是1,那么就是true,否则就是maybe
                {
                    if(a[1][i])
                    {
                        flag=1;
                        break;
                    }
                }
                if(flag==0)
                    cout<<"True"<<endl;
                else cout<<"Maybe"<<endl;
            }
        }
        cout<<endl;
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值