POJ3274《Gold Balanced Lineup》方法:哈希

题目大意:最多有10w个牛,每个牛有最多30个特征,比如特征 10,可以表示为二进制形式1010,现在要求出在一个连续区间,牛的每个特征数目相等时,连续区间的最大长度。

解题思路:sum[i][j]表示从第1个到第i个牛,特征j出现的总数,即要求sum[a][0] - sum[b][0] = sum[a][1] - sum[b][1] = sum[a][k-1] - sum[b][k-1]。式子可转化为sum[a][1] - sum[a][0] = sum[b][1] - sum[b][0],sum[a][2] - sum[a][0] = sum[b][2] - sum[b][0],因此可以令c[i][j] = sum[i][j] - sum[i][0],最终即要找到使c[a][]和c[b][]相等的区间最大长度。因为题目数量级为10w,因此不能两两之间相互比较,所以用哈希函数来将c[][]相等的数放入同一个地址中,具体的key是c[][1]*1+c[][2]*2...的和,prime取100003。

// 38236k 1079ms #include #include using namespace std; #define N 100003 #define K 30 const int prime = 100003; class HashTable { public: int pi; HashTable *next; HashTable() { next = NULL; } }; class HashTable *hashtable[N]; int n, k; //奶牛数,特征数 int f[N][K]; int sum[N][K]; // sum[i][j]表示从f[1][j]到f[i][j]的第j个数字之和 int c[N][K]; // c[i][y] = sum[i][y] - sum[i][0] int maxlen; bool cmp(int i, int j) { for (int m = 0; m < k; ++m) if (c[i][m] != c[j][m]) return false; return true; } void Hash(int i) { int key = 0; for (int j = 1; j < k; ++j) { key += c[i][j] * j; } key = abs(key) % prime; if (!hashtable[key]) { hashtable[key] = new class HashTable; hashtable[key]->pi = i; } else { // key冲突 class HashTable *ph = hashtable[key]; if (cmp(ph->pi, i)) { // 看c[][]与当前c[i][]是否相等 if (i - (ph->pi) > maxlen) { maxlen = i - (ph->pi); } // 因为pi和i对应列数字相等,且pi地址必定比i小,因此不要保存i return; } else { while (ph->next) { // 看key冲突的从第二个开始与c[i][]是否相等 if (cmp(ph->next->pi, i)) { if (i - (ph->next->pi) > maxlen) { maxlen = i - (ph->next->pi); } // 同样不需保存i return; } ph = ph->next; } //key冲突但c[][]不全相同,需要保存i class HashTable * tmp = new class HashTable; tmp->pi = i; ph->next = tmp; } } } int main() { //freopen("temp.txt", "r", stdin); while (cin >> n >> k) { maxlen = 0; memset(hashtable, 0, sizeof(hashtable)); for (int i = 0; i < k; ++i) { sum[0][i] = 0; c[0][i] = 0; } Hash(0); int num; for (int i = 1; i <= n; ++i) { cin >> num; for (int j = 0; j < k; ++j) { f[i][j] = num % 2; num /= 2; sum[i][j] = sum[i-1][j] + f[i][j]; c[i][j] = sum[i][j] - sum[i][0]; } Hash(i); } cout << maxlen << endl; } return 0; }

你可能感兴趣的:(POJ)