3690状态压缩+暴力
生活随笔
收集整理的這篇文章主要介紹了
3690状态压缩+暴力
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
題意:
? ? ? 給你一個矩陣,上面只有*和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; }
總結
以上是生活随笔為你收集整理的3690状态压缩+暴力的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ZOJ3261并查集逆向处理
- 下一篇: 3764树上的异或值(自己研究的静态字典