码迷,mamicode.com
首页 > 其他好文 > 详细

BZOJ 1898 ZJOI 2004 Swamp 沼泽鳄鱼 矩阵乘法

时间:2015-03-04 14:41:11      阅读:176      评论:0      收藏:0      [点我收藏+]

标签:bzoj   zjoi2014   矩阵乘法   

题目大意

给出一张无向图,这个图中有一些鱼,他们不同的时间会出现在固定的位置,呈周期性循环,一个人要在这个图上走,他不能和鱼同时在一个点上。问从s到t走k步有多少种方案。

思路

注意到鱼的循环只可能是2/3/4,也就是说最多经过12个时间点之后,状态又会和一开始相同。所以预处理12个矩阵用来转移。分为k/12和k%12来处理。
当鱼在一个位置上的时候,当前时间从这个位置出发的一行和上一个时间到达这个点的一列需要清零。

CODE

#define _CRT_SECURE_NO_WARNINGS

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define MAX 60
#define MO 10000
using namespace std;

int points;

struct Matrix{
    int num[MAX][MAX];
    int w,h;

    Matrix(int _,int __):w(_),h(__) {
        memset(num,0,sizeof(num));
    }
    Matrix() {
        memset(num,0,sizeof(num));
    }
    Matrix operator *(const Matrix &a)const {
        Matrix re(w,a.h);
        for(int i = 1; i <= w; ++i)
            for(int j = 1; j <= a.h; ++j) {
                for(int k = 1; k <= h; ++k)
                    re.num[i][j] += num[i][k] * a.num[k][j];
                re.num[i][j] %= MO;
            }
        return re;
    }
    void ClearHor(int line) {
        for(int i = 1; i <= points; ++i)
            num[line][i] = 0;
    }
    void ClearVer(int line) {
        for(int i = 1; i <= points; ++i)
            num[i][line] = 0;
    }
}src[20];

struct Fish{
    int cnt,num[10];

    void Read() {
        scanf("%d",&cnt);
        for(int i = 0; i < cnt; ++i)
            scanf("%d",&num[i]),++num[i];
    }
}fish[MAX];

int edges,s,t;
long long k;
int fishes;

Matrix QuickPower(Matrix a,long long y)
{
    Matrix re(points,points);
    for(int i = 1; i <= points; ++i)
        re.num[i][i] = 1;
    while(y) {
        if(y&1) re = re * a;
        a = a * a;
        y >>= 1;
    }
    return re;
}

int main()
{
    cin >> points >> edges >> s >> t >> k;
    ++s,++t;
    Matrix map(points,points);
    for(int x,y,i = 1; i <= edges; ++i) {
        scanf("%d%d",&x,&y);
        ++x,++y;
        map.num[x][y] = map.num[y][x] = 1;
    }
    for(int i = 0; i < 12; ++i)
        src[i] = map;
    cin >> fishes;
    for(int i = 1; i <= fishes; ++i)
        fish[i].Read();
    for(int i = 0; i < 12; ++i) {
        for(int j = 1; j <= fishes; ++j) {
            int pos = fish[j].num[i % fish[j].cnt];
            if(i)   
                src[i - 1].ClearVer(pos);
            src[i].ClearHor(pos);
        }
    }
    Matrix base(points,points);
    for(int i = 1; i <= points; ++i)
        base.num[i][i] = 1;
    for(int i = 0; i < 12; ++i)
        base = base * src[i];
    Matrix ans = QuickPower(base,k / 12);
    k %= 12;
    for(int i = 0; i < k; ++i)
        ans = ans * src[i];
    cout << ans.num[s][t] << endl;
    return 0;
}

BZOJ 1898 ZJOI 2004 Swamp 沼泽鳄鱼 矩阵乘法

标签:bzoj   zjoi2014   矩阵乘法   

原文地址:http://blog.csdn.net/jiangyuze831/article/details/44059555

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!