3690状态压缩+暴力
来源:互联网 发布:淘宝客要怎么推广 编辑:程序博客网 时间:2024/05/29 10:19
题意:
给你一个矩阵,上面只有*和0(最大1000*1000),然后有t(最大100)组询问,每组询问给你一个小矩阵(最大50*50),问这t个矩阵中有多少个是在大矩阵中出现的。
思路:
给你一个矩阵,上面只有*和0(最大1000*1000),然后有t(最大100)组询问,每组询问给你一个小矩阵(最大50*50),问这t个矩阵中有多少个是在大矩阵中出现的。
思路:
这个题目做的有点蛋疼,说下我的第一个思路,我的想法是把所有的数据都按照行去压缩成longlong的,因为最大50位<64位 可以直接每行都压缩了,每个p*q的小矩阵就变成p个longlong的数字了,然后在把大矩阵同样处理,可以得到n*(m-q+1)个longlong的数字,然后就直接暴力的去KMP匹配,结果超时了,很是不解,反复改,优化,还是超时,最后没办法用了网上说的那个暴力,第一次还是超时了,看讨论,发现枚举的时候是i和j调换一下,按照算法的思路看时间复杂度没变,但是竟然ac了,MD,说实话,枚举的时间复杂度最坏是O(1000*1000*50*100),而KMP的时间复杂度是O(1000*(1000+50)*100)其实把i,j调换后AC了已经想到这个题目的数据的问题,我是在想不明白在概率的角度去考虑为什么横着枚举会比竖着枚举快(目前感觉就是后台数据的问题),但是如果是用KMP去跑的话把状态压缩改成竖着压缩应该能过,而且有可能会更快,这蛋疼数据。下面是暴力AC的代码和横着的KMP代码,暴力的好像是1500多AC的,横着的KMP超时了,有兴趣可以改成竖着试试,但是我不想改了,有点恶心了,那个KMP我优化了n多次,也重敲了n多次,对于这样的数据A不A已经不再重要。
状态压缩+暴力#include<stdio.h>long long hash1[1005][1005];long long hash2[55];bool jude(int n ,int m ,int p ,int q){ int i ,j ,k; for(i = 1 ;i <= n - p + 1 ;i ++) for(j = 1 ;j <= m - q + 1 ;j ++) { for(k = 1 ;k <= p ;k ++) if(hash1[i+k-1][j] != hash2[k]) break; if(k == p + 1) return 1; } return 0;}int main (){ int n ,m ,t ,p ,q ,cas = 1 ,i ,j; char str[1005]; long long T ,O ,I = 1; while(~scanf("%d %d %d %d %d" ,&n ,&m ,&t ,&p ,&q) && n + m + t + p + q) { for(i = 1 ;i <= n ;i ++) { scanf("%s" ,str); T = 0; for(j = 1 ;j <= m ;j ++) { O = str[j-1] == '*'; T = T * 2 + O; if(j >= q) { hash1[i][j-q+1] = T; if(str[j-q]=='*') T = T - (I<<(q-1)); } } } int ans = 0; while(t--) { for(i = 1 ;i <= p ;i ++) { scanf("%s" ,str); T = 0; for(j = 1 ;j <= q ;j ++) { O = str[j-1] == '*'; T = T * 2 + O; } hash2[i] = T; } if(p <= n && q <= m && jude(n ,m ,p ,q)) ans ++; } printf("Case %d: %d\n" ,cas ++ ,ans); } return 0;}状态压缩+KMP#include<stdio.h>#include<string.h>#define N 1000 + 10#define M 50 + 5long long hash1[N][N];long long hash2[M];int next[M];int map[N][N];void Get_Next(int m){ int j = 0 ,k = -1; next[0] = -1; while(j < m) { if(k == -1 || hash2[j] == hash2[k]) next[++j] = ++k; else k = next[k]; } return ;}int KMP(int n ,int m ,int J){ int i ,j; for(i = j = 0 ;i < n ;) { if(hash1[i][J] == hash2[j]) { if(j == m - 1) return 1; i ++ ,j ++; } else { j = next[j]; if(j == -1) j = 0 ,i ++; } } return 0;}int main (){ int n ,m ,t ,p ,q ,i ,j ,cas = 1; char str[N]; while(~scanf("%d %d %d %d %d" ,&n ,&m ,&t ,&p ,&q) && n + m + t + p + q) { for(i = 1 ;i <= n ;i ++) { scanf("%s" ,str); for(j = 0 ;j < m ;j ++) map[i][j+1] = str[j] == '*'; } long long T ,O = 1; if(p <= n && q <= m) for(i = 1 ;i <= n ;i ++) { T = 0; for(j = 1 ;j <= m ;j ++) { T = T * (long long)2 + (long long)map[i][j]; if(j >= q) { hash1[i-1][j-q] = T; if(map[i][j-q+1]) T -= (O << (q - 1)); } } } for(i = 0 ;i <= m ;i ++) hash1[n][i] = -1; int ans = 0; while(t--) { for(i = 1 ;i <= p ;i ++) { scanf("%s" ,str); T = 0; for(j = 0 ;j < q ;j ++) { if(str[j] == '*') O = 1; else O = 0; T = T * 2 + O; } hash2[i-1] = T; } hash2[p] = -1; if(p > n || q > m) continue; Get_Next(p); for(i = 0 ;i <= m - q ;i ++) { if(KMP(n ,p ,i)) { ans ++; break; } } } printf("Case %d: %d\n" ,cas ++ ,ans); } return 0;}
0 0
- 3690状态压缩+暴力
- HDU 1557 权利指数 状态压缩 暴力
- UVA1508-Equipment(状态压缩+暴力枚举)
- POJ 3279 Fliptile(状态压缩+暴力)
- POJ 3279 (状态压缩暴力枚举)
- Flip Game(poj1753,状态压缩+暴力枚举)
- 2013杭州站A题||hdu4770 状态 压缩+暴力枚举
- CF 474C Captain Marmot[暴力枚举 || bfs状态压缩 ]
- POJ - 1691 Painting A Board (状态压缩 + 暴力)
- hdu 1044 Collect More Jewels【暴力Bfs+状态压缩】
- HDU 4770 Lights Against Dudely 【状态压缩+暴力枚举】
- HDU4770 —— Lights Against Dudely (状态压缩,暴力枚举)
- HDU 4403 A very hard Aoshu problem (暴力+状态压缩)
- POJ 3279 Fliptile 开关灯问题(状态压缩加暴力搜索)
- HDU5816(2016多校第七场)——Hearthstone(暴力枚举,状态压缩)
- 7_11_A题 Lights Against Dudely [HDU 4770] (状态压缩+暴力)
- UVa --- 10464 Even Parity 偶数矩阵 【状态压缩 + 暴力枚举 + 思维】
- problem/868/C Qualification Rounds 思维题 状态压缩 暴力枚举
- 灯塔问题
- 数列有序
- openGL常用的函数
- 软件测试职业规划
- FZU 2082 过路费 (树链剖分)
- 3690状态压缩+暴力
- 关于求第几天的问题
- JPA相关内容
- POJ_3278 Catch That Cow(BFS)
- 链表反转的递归和非递归实现方式
- Oracle 11g Golden Gate DDL单向同步实例演示
- C语言代码实现 ls
- 3764树上的异或值(自己研究的静态字典树)
- JS获取表单所有元素(键值对方式)