ZOJ 3497 Mistwald (矩阵快速幂解决类似图论问题)
2016-02-01 23:10
387 查看
点击打开链接
这道题的题意大概是有一个n*m的图,会告诉你每一个点的出边,与哪四个点相连(可能是重复的),注意这是单向的连接。问从起点(1,1)开始,走P步之后,是一定到终点(n,m),还是可能到,还是不可能到终点?其中在行走的过程中,除了第P步到达的点,其他都不能是终点,但是可以重复经过其他点。
这道题由于方便起见,把起点设置为(0,0),终点就是(n-1,m-1),按行优先遍历,给每个点按顺序编号,然后再做一个邻接矩阵A。A^K的第i行第j列的数代表从编号为i的点走k步是否能到达j。
最关键的一步,就是把终点的出边给删掉。这样就永远不可以从终点出发到另外一个点了。
理解的过程,可以把A^K的计算过程在脑海里模拟一遍,先假设不考虑终点是不是经过,那么新的矩阵的a[i][j]是如何产生的,特别要关注 a[i][k]&&a[k][j] ,k相当于从i到j的一个中间点。
再讨论一下p=0的特殊情况。
这道题的题意大概是有一个n*m的图,会告诉你每一个点的出边,与哪四个点相连(可能是重复的),注意这是单向的连接。问从起点(1,1)开始,走P步之后,是一定到终点(n,m),还是可能到,还是不可能到终点?其中在行走的过程中,除了第P步到达的点,其他都不能是终点,但是可以重复经过其他点。
这道题由于方便起见,把起点设置为(0,0),终点就是(n-1,m-1),按行优先遍历,给每个点按顺序编号,然后再做一个邻接矩阵A。A^K的第i行第j列的数代表从编号为i的点走k步是否能到达j。
最关键的一步,就是把终点的出边给删掉。这样就永远不可以从终点出发到另外一个点了。
理解的过程,可以把A^K的计算过程在脑海里模拟一遍,先假设不考虑终点是不是经过,那么新的矩阵的a[i][j]是如何产生的,特别要关注 a[i][k]&&a[k][j] ,k相当于从i到j的一个中间点。
再讨论一下p=0的特殊情况。
#include<cstdio> #include<cstring> struct matrix{ int a[30][30]; }base, ans, re; int n, m; matrix multiply(matrix u, matrix v) { matrix tmp; for (int i = 0; i < n*m; i++) for (int j = 0; j < n*m; j++) { tmp.a[i][j] = 0; for (int k = 0; k < n*m; k++) if (u.a[i][k] && v.a[k][j]) { tmp.a[i][j] = 1; break; } } return tmp; } void fast_mod(int l) { while (l) { if (l & 1) ans = multiply(ans, base); base = multiply(base, base); l >>= 1; } } int main() { int t, q, p, s; int x[5], y[5], num[5]; scanf("%d", &t); getchar(); while (t--) { memset(re.a, 0, sizeof(re.a)); scanf("%d%d", &m, &n); getchar(); for (int i = 0; i < m; i++) for (int j = 0; j < n; j++) { scanf("((%d,%d),(%d,%d),(%d,%d),(%d,%d))", &x[0], &y[0], &x[1], &y[1], &x[2], &y[2], &x[3], &y[3]); getchar(); // 输入格式要注意 注意要吃回车 if (i == (m-1) && j == (n-1)) continue; //最关键的一步 num[4] = i*n+j; for (int k = 0; k < 4; k++) num[k] = (x[k]-1)*n + y[k]-1; for (int k = 0; k < 4; k++) re.a[num[4]][num[k]] = 1; } scanf("%d", &q); getchar(); while (q--) { scanf("%d", &p); getchar(); if (p == 0) { if (n == 1 && m == 1) printf("True\n"); else printf("False\n"); continue; } memcpy(base.a, re.a, sizeof(base.a)); // 把一个数组赋值给另外一个数组 memset(ans.a, 0, sizeof(ans.a)); for (int i = 0; i < n*m; i++) ans.a[i][i] = 1; fast_mod(p); s = 0; for (int i = 0; i < n*m-1; i++) if (ans.a[0][i]) s++; if (ans.a[0][n*m-1] == 1) { if (s == 0) printf("True\n"); else printf("Maybe\n"); } else printf("False\n"); } printf("\n"); } return 0; }
相关文章推荐
- Dos学习笔记(1)dir命令
- Codeforces 222D Olympiad(贪心)
- 小技巧总结
- 第三百零五天 how can I 坚持
- storm安装
- Java Map简单使用
- 设计模式之抽象工厂
- HTTP2.0那些事
- 网络OSI参考模型
- 关于QT、QT creator和编译器,新手入门必知的一些知识
- yuv 与 rgb 互相转化的色差问题
- JavaScript第五课——数据类型(String类型、Object类型)
- iOS开发的小技巧(断点打印)
- HTML5指南针
- 顿
- 定时器
- 节后开工,请把这9句话写在你的办公桌上!
- 第13讲-数值型数据的存储-练习
- Go语言笔记:base64/sha1的使用
- 音频框架TheAmazingAudioEngine实现音效