POJ 3274 Gold Balanced Lineup

 

这个题看了题解之后才会写的,每头牛最多有k个属性,用给出数字的对应二进制位表示,

0为没有这种属性,1为具有这种属性。要求的是最长的一个牛的序列,使得每种属性出现

的次数相同。参考网上的hash函数  ret = ((ret << 2) + (a[i] >> 4)) ^ (a[i] << 10); 

用sum[i][j]表示前i头牛的第j种属性出现的次数。用c[i][j]存储sum[i][j] - sum[i][0]的

值,代表前i头牛第j种属性出现次数与第0种属性出现次数的差值。如果存在i1和i2,使得

c[i1][j] = c[i2][j]   0< j < k, i1到i2这一段就是符合要求的一个解。找到最长的i2 - i1

就是答案。这里理解过来就是在i1到i2所有属性出现次数的增量都相同。

 

[分析]:以样例为例:

转换成二进制

111

110

111

010

001

100

010

sum[i][j]的值,累加的过程。

111    

221    

332     

342    

343

443

453

 

都减去第0种属性出现的次数和

000

110 i1

110

120

010

110 i2

120

到此可以看出规律, i2 - i1就是所求答案。

 

/*Accepted    26420 KB    266 ms    C++    1471 B    2012-08-24 14:41:44*/

#include<stdio.h>

#include<string.h>

#include<stdlib.h>



const int MAXN = 100100;

const int MAXK = 32;



int sum[MAXN][MAXK], c[MAXN][MAXK];

int first[MAXN], next[MAXN], v[MAXN], e;

int n, p, ans;



void addedge(int x, int y)

{

    next[e] = first[x], v[e] = y;

    first[x] = e ++;

}



int hash(int c[])

{

    int ret = 0, i;

    for(i = 0; i < p; i ++)

        ret = ((ret << 2) + (c[i] >> 4)) ^ (c[i] << 10);

    ret = (ret % MAXN + MAXN) % MAXN;

    return ret;

}



void cal()

{

    int i, j, k, a, h;

    memset(sum, 0, sizeof sum);

    memset(c, 0, sizeof c);

    memset(first, -1, sizeof first);

    e = ans = 0;

    addedge(hash(c[0]), 0);

    for(i = 1; i <= n; i ++)

    {

        scanf("%d", &a);

        for(j = 0; j < p; j ++)

        {

            sum[i][j] = sum[i - 1][j] + (1 & a);

            a >>= 1;

        }

        for(j = 0; j < p; j ++)

        {

            c[i][j] = sum[i][j] - sum[i][0];

        }

        h = hash(c[i]);

        for(j = first[h]; j != -1; j = next[j])

        {

            bool ok = true;

            for(k = 0; k < p; k ++)

            {

                if(c[v[j]][k] != c[i][k])

                {

                    ok = false;

                    break;

                }

            }

            if(ok && ans < i - v[j])

                ans = i - v[j];



        }

        addedge(h, i);

    }

}



int main()

{

    while(scanf("%d%d", &n, &p) != EOF)

    {

        cal();

        printf("%d\n", ans);

    }

    return 0;

}

 

 

 

你可能感兴趣的:(poj)