HDU 6046 hash(搜索标识)
来源:互联网 发布:如何把linux改为英语 编辑:程序博客网 时间:2024/06/09 16:55
hash
Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others)Total Submission(s): 122 Accepted Submission(s): 33
One day,he generates a large matrix by Jenkins one-at-a-time hash:
inline unsigned sfr(unsigned h, unsigned x) {
return h >> x;
}
int f(LL i, LL j) {
LL w = i * 1000000ll + j;
int h = 0;
for(int k = 0; k < 5; ++k) {
h += (int) ((w >> (8 * k)) & 255);
h += (h << 10);
h ^= sfr(h, 6);
}
h += h << 3;
h ^= sfr(h, 11);
h += h << 15;
return sfr(h, 27) & 1;
}
Obviously,it's a 1e6*1e6 matrix.The data is at row i column j is f(i,j).Note that i and j are both numbered from 1.
Then he gets some matrices sized 1e3*1e3 from the matrix above.But he forgets their original postion.Can you help him to find them out?You just are asked to tell Qscqesze the left-top corner's postion.
Here come with T cases.Each case is consist of 1000 0/1-strings sized 1000.
For convenience,the sample input is 10*10.And the real testcase is 1e3*1e3.
10000011100000011001101111111000011110010011010101010010010010100111110111100101000111011101100110100
Case #1 :123456 234567
题目大意:
给你一个1e6*1e6的bool矩阵的生成方法,每次给你一个1e3*1e3的bool矩阵,问这个矩阵在大矩阵中的位置。
解题思路:
首先这个矩阵的生成方式是没有任何规律的,可以认为是随机的。大矩阵非常大,即没办法快速的生成也存不下。由于unsigned long long能保存的状态数远大于1e6*1e6,所以基本上可以认为每个位置的标识矩阵都是不同的,所以我们可以在大矩阵中找一些小矩阵作为标识,小矩阵匹配之后再在这个位置匹配整个输入矩阵。
由于unsigned long long能存64位二进制数,我们就可以以8*8的小矩阵作为标识矩阵。接下来就是隔多远取一个标记的问题了,我们可以根据鸽笼原理知道当标记的间隔小于输入矩阵的边长-2*标记矩阵的边长时,至少一定有一个标识矩阵在输入矩阵中。那么我们就取980作为标识间隔。
接下来就是代码实现方式了。先在大矩阵中每隔980行列,取一个8*8的小矩阵,状压到一个unsigned long long中,用hashmap记录位置,然后对于输入矩阵枚举8*8小矩阵的左上角,判断这个矩阵是否是标识矩阵,如果是的话,就可以计算出输入矩阵的左上角坐标,利用这个坐标把输入矩阵与大矩阵匹配,如果匹配成功则这个坐标就是答案。
关于这样写的时间复杂度。首先预处理出标识矩阵的时间复杂度为:(1e6)/980*(1e6)/980*8*8,对输入矩阵枚举标识矩阵并匹配的时间复杂度为:(1e3)*(1e3)*8*8。由于基本上可以认为每个位置的标识矩阵都是不同的,所以基本上可以认为最终检测只有一次,时间复杂度为(1e3)*(1e3)。所以总时间复杂度为O(7*10^7),题目限时5s,就可以过了。
AC代码:
#include <iostream>#include <algorithm>#include <cstdio>#include <cstring>#include <cstdlib>#include <cmath>#include <ctime>#include <vector>#include <queue>#include <stack>#include <deque>#include <string>#include <map>#include <set>#include <list>using namespace std;#define INF 0x3f3f3f3f#define LL long long#define ULL unsigned long long#define fi first#define se second#define mem(a,b) memset((a),(b),sizeof(a))const int MAXL=1000000;const int MAXN=1000;char s[MAXN+2][MAXN+2];//输入矩阵struct HashMap{ const static int MOD=1196473; int head[MOD],next[2*MAXN*MAXN],cnt,y[2*MAXN*MAXN],x[2*MAXN*MAXN]; ULL val[2*MAXN*MAXN]; inline void insert(ULL _val,int _y,int _x) { int p=_val%MOD; ++cnt; val[cnt]=_val; y[cnt]=_y; x[cnt]=_x; next[cnt]=head[p]; head[p]=cnt; } pair<int,int> find(ULL _val) { int p=_val%MOD; for(int i=head[p];i;i=next[i]) if(val[i]==_val) return make_pair(y[i], x[i]); return make_pair(0, 0); }}save;//保存标识矩阵的状压值和坐标inline unsigned sfr(unsigned h, unsigned x){ return h >> x; } int f(LL i, LL j){ LL w = i * 1000000ll + j; int h = 0; for(int k = 0; k < 5; ++k) { h += (int) ((w >> (8 * k)) & 255); h += (h << 10); h ^= sfr(h, 6); } h += h << 3; h ^= sfr(h, 11); h += h << 15; return sfr(h, 27) & 1; } bool judge(int y,int x)//最终判断{ for(int i=0;i<MAXN;++i) for(int j=0;j<MAXN;++j) if(s[i][j]-'0'!=f(y+i, x+j)) return false; return true;}int main(){ for(int y=1;y<=MAXL;y+=980)//预处理出标识矩阵 for(int x=1;x<=MAXL;x+=980) { ULL res=0; for(int i=0;i<8;++i) for(int j=0;j<8;++j) res=(res<<1)|f(y+i, x+j); save.insert(res, y, x); } int T_T; scanf("%d",&T_T); for(int cas=1;cas<=T_T;++cas) { int ansy=0,ansx=0; for(int i=0;i<MAXN;++i) scanf("%s",s[i]); for(int y=0;y+7<MAXN;++y) { for(int x=0;x+7<MAXN;++x) { ULL res=0; for(int i=0;i<8;++i) for(int j=0;j<8;++j) res=(res<<1)|(s[y+i][x+j]=='1'); pair<int, int> p=save.find(res); if(p.fi&&judge(p.fi-y, p.se-x))//找到答案 { ansy=p.fi-y; ansx=p.se-x; break; } } if(ansy) break; } printf("Case #%d :%d %d\n",cas,ansy,ansx); } return 0;}
- HDU 6046 hash(搜索标识)
- hdu 1043(搜索 + 康拓展开hash)
- HDU-6046 hash(哈希)
- HDU 6046 hash 哈希
- HDU 4334 Trouble(Hash)
- HDU 1067(HASH + BFS)
- hdu 1496(hash经典)
- HDU 1425 sort (hash)
- hdu 1496 Equations (hash)
- HDU 1496 Equations(hash)
- (hash)hdu 1496 Equations
- hdu 5199 Gunner(hash)
- hdu 1496 Equations(hash)@
- HDU 4821 String(Hash)
- hdu 4622 Reincarnation(hash)
- HDU 6046 hash (HASH, 2017 Multi-Univ Training Contest 2)
- HDU6076(dp+记忆化搜索+hash)
- POJ-1175:Starry Night(搜索+hash)
- Java 实现 word文件添加 图片水印 jacob.jar
- C#两个DataTable拷贝问题:该行已经属于另一个表的解决方法
- velocity使用(一)--简介
- 李宏毅机器学习课程4~~~分类:概率生成模型
- VisualVM java监控工具
- HDU 6046 hash(搜索标识)
- 1011 Regular polygon 6055之神奇的count与[]
- 一些css选择器的使用
- PCIe学习笔记(27)--- PL
- iOS 下拉刷新-自定义
- Eclipse技巧
- C
- JSON转Map的几种方式
- HDU 6033 Add More Zero 数论 水题