ZOJ 3497 Mistwald
来源:互联网 发布:怎样看b超单上的数据 编辑:程序博客网 时间:2024/06/06 16:48
http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3497
题意 : 给你一个5 * 5的矩阵, 存在一些单向边(存在自环), 然后问你从 (1, 1) -> (n, m)走k步到达 这一情况是否存在。
思路 :先把每个点重新标号为 1, 2, 3 ... n * m, 然后构造成(n * m) * (n * m) 的矩阵, 最后用矩阵乘法做。
比如 : G[i][j][k] : 表示从i -> j 走k步的路线数目。
则 G[i][j][t1 + t2] = ∑( G[i][k][t1] * G[k][j][t2] )其中k >= 1 && k < n * m 并且i != (n * m)注 : 题中提到从(n, m)这个点不能再走到其它点的。
观察式子可以发现其实就是矩阵乘法。 所以这题可以转换为矩阵乘法判断了。 注意别TLE。
PS : 比赛的时候没想出, 后来发现这其实就类似这一题 (这题以前是肉鸽教我的, 当时只当是矩阵快速幂在做, 并没有深入了解其含义)。
推荐一篇和矩阵有关的好文章 : http://www.matrix67.com/blog/archives/276
然后么,我对于Maybe和True的理解可能有点问题, 不过A了。贴下代码。
CODE :
#include <cstdio>#include <cstring>#include <algorithm>using namespace std;const int maxn = 35;struct mat { int a[maxn][maxn];}bit[30], G;int n, N, M;mat mul(mat a, mat b) { mat ans; for (int i = 1; i < n; i++) { for (int j = 1; j <= n; j++) { ans.a[i][j] = 0; for (int k = 1; k < n && !ans.a[i][j]; k++) { ans.a[i][j] += a.a[i][k] * b.a[k][j]; } if (ans.a[i][j] >= 2)ans.a[i][j] = 1; } } return ans;}void init(mat & a) { for (int i = 1; i <= n; i++) { for (int j = 1; j <= n; j++)a.a[i][j] = 0; }}void read(int u) { char ss[maxn]; scanf("%s", ss); int m = strlen(ss), cnt = 0, aa[maxn]; for (int i = 0; i < m; i++) { if (ss[i] >= '0' && ss[i] <= '9') { aa[++cnt] = ss[i] - '0'; } } for (int i = 1; i <= cnt; i += 2) { if (u != n)G.a[u][(aa[i] - 1) * M + aa[i+1]] = 1; }}void work() { bit[1] = G; for (int i = 2; i <= 29; i++) { bit[i] = mul(bit[i-1], bit[i-1]); }}void show(mat a) { for (int i = 1; i <= n; i++) { for (int j = 1; j <= n; j++)printf("%d", a.a[i][j]); printf("\n"); }}int isok(int x) { int c = 1; mat res; init(res); for (int i = 1; i <= n; i++)res.a[i][i] = 1; while (x) { if (x & 1) res = mul(res, bit[c]); c++; x >>= 1; } return res.a[1][n];}int main() { int T; while (scanf("%d", &T) != EOF) { while (T--) { scanf("%d%d", &N, &M); n = N * M; init(G); for (int i = 1; i <= N; i++) { for (int j = 1; j <= M; j++) { read((i - 1) * M + j); } } work(); int Q, num = 0; for (int i = 0; i <= n * n; i++) { num += isok(i); } scanf("%d", &Q); while (Q--) { int q; scanf("%d", &q); bool ok = isok(q); if (!ok) { printf("False\n"); }else { if (num >= 2)printf("Maybe\n"); else printf("True\n"); } } printf("\n"); } } return 0;}
0 0
- ZOJ 3497Mistwald
- zoj 3497 Mistwald
- zoj 3497 mistwald
- ZOJ 3497 Mistwald
- ZOJ 3497 Mistwald
- zoj 3497 Mistwald
- ZOJ 3497Mistwald
- zoj 3497 Mistwald (矩阵应用)
- ZOJ 3497Mistwald 矩阵加速DP
- zoj-3497-Mistwald-矩阵
- ZOJ 3497 Mistwald(矩阵快速幂)
- zoj 3497 Mistwald 矩阵快速幂
- zoj 3497 Mistwald 矩阵快速幂
- ZOJ 3497 Mistwald(矩阵快速幂)
- ZOJ 3497Mistwald(矩阵快速幂)
- ZOJ 3497 Mistwald【矩阵快速幂】【图论】
- zoj 3497 Mistwald 矩阵快速幂
- zoj 3497 Mistwald(矩阵快速幂)
- android退出应用方式归纳总结
- hdu 3836 强联通分量分解
- storm-kafka-plus源码阅读
- 7.1 第二块,第一节 objective-c
- No result defined for action cn.com.struts2.action.LoginAction and result succeed
- ZOJ 3497 Mistwald
- iOS数据存取和对象序列化
- 九度:1022:游船出租
- Cocos2d-X 2.2 离线 API Referen 下载 200多M
- 黑马程序员06——OC之Fundation(NSArray基本使用)
- Combinations
- 高效能程序员的七个习惯
- 帝国的重生
- hdu 2113 被虐!!