您的位置:首页 > 编程语言 > Go语言

POJ3274-Gold Balanced Lineup

2011-07-30 21:47 190 查看
转载请注明出处:優YoUhttp://user.qzone.qq.com/289065406/blog/1309220772

大致题意:[/b]

[/b]


[/b]

解题思路:[/b]

经典题,不转化问题很难做,先根据官方的方法转化问题,把“求最远的两行间各个特征出现次数相等”转化为“求最远的相同两行”,再用Hash查找。

这是官方解题报告——

Considerthepartialsumsequenceofeachofthekfeaturesbuiltbytakingthe

sumofallthevaluesuptopositioni.Theproblemisequivalentto:

Givenanarrays
[k],findi,j,withthebiggestseparationforwhichs[i]

[l]-s[j][l]isconstantforalll.

Theproblemisnowtodothisefficiently.Noticethats[i][l]-s[j][l]being

constantforalllisequivalenttos[i][l]-s[j][l]=s[i][1]-s[j][1]forall

l,whichcanberearrangedtobecomes[i][l]-s[i][1]=s[j][l]-s[j][1]forall

l.Therefore,wecanconstructanotherarraya
[k]wherea[i][j]=s[i][j]-

s[i][1]andthegoalistofindiandjwiththebiggestseparationforwhich

a[i][l]=a[j][l]foralll.

Thiscanbedonebysortingallthea[i]entries,whichtakesO(nklogn)time

(althoughinpracticerarelywillallkelementsbecompared).Another

alternativeistogobyhashing,givinganO(nk)solution.Bothsolutionsare

fairlystraightforwardoncethefinalarrayisconstructed.

大概意思就是:

数组sum[i][j]表示从第1到第i头cow属性j的出现次数。

所以题目要求等价为:

求满足

sum[i][0]-sum[j][0]=sum[i][1]-sum[j][1]=.....=sum[i][k-1]-sum[j][k-1](j<i)

中最大的i-j

将上式变换可得到

sum[i][1]-sum[i][0]=sum[j][1]-sum[j][0]

sum[i][2]-sum[i][0]=sum[j][2]-sum[j][0]

......

sum[i][k-1]-sum[i][0]=sum[j][k-1]-sum[j][0]

令C[i][y]=sum[i][y]-sum[i][0](0<y<k)

初始条件C[0][0~k-1]=0

所以只需求满足C[i][]==C[j][]中最大的i-j,其中0<=j<i<=n。

C[i][]==C[j][]即二维数组C[][]第i行与第j行对应列的值相等,

那么原题就转化为求C数组中相等且相隔最远的两行的距离i-j[/b]。

以样例为例

73

7

6

7

2

1

4

2


先把7个十进制特征数转换为二进制,并逆序存放到特征数组feature[][],得到:

7à111

6à011

7à111

2à010

1à100

4à001

2à010

(行数为cow编号,自上而下从1开始;列数为特征编号,自左到右从0开始)

再求sum数组,逐行累加得,sum数组为

111

122

233

243

343

344

354

再利用C[i][y]=sum[i][y]-sum[i][0]求C数组,即所有列都减去第一列

注意C数组有第0行,为全0

000à第0行

000

011

011

021

010

011

021

显然第2行与第6行相等,均为011,且距离最远,距离为6-2=4,这就是所求。

但是最大数据有10W个,即10W行,因此不能直接枚举找最大距离,必须用Hash查找相同行,找到相同行再比较最大距离。

注意C数组的值可能为负数,因此生成key值时要注意保证key为非负数。

Source修正:

USACO2007MarchGold

http://www.cppblog.com/Felicia/archive/2007/12/29/39923.html

官方对Hint的解释:

INPUTDETAILS:

Thelinehas7cowswith3features;thetablebelowsummarizesthe
correspondence:
Feature3:1110010
Feature2:1111001
Feature1:1010100
Key:7672142
Cow#:1234567

OUTPUTFORMAT:

*Line1:Asingleintegergivingthesizeofthelargestcontiguous
balancedgroupofcows.

OUTPUTDETAILS:

Intherangefromcow#3tocow#6(ofsize4),eachfeatureappears
inexactly2cowsinthisrange:
Feature3:1001->twototal
Feature2:1100->twototal
Feature1:1010->twototal
Key:7214
Cow#:3456

*********************************************************************

//MemoryTime
//44152K1141MS

#include<iostream>
#include<cmath>
usingnamespacestd;

constintsize=100001;
constintmod=99991;

intfeature[size][30];//feature[i][j]标记第i只牛是否有特征j
intsum[size][30];//从第1到第i只牛,特征j总共出现了sum[i][j]次
intc[size][30];//c[i][j]=sum[i][j]-sum[i][0],即所有列都减去第一列后,值保存在c[][]
intN;//牛数量
intK;//特征数
intMaxLen;//最大距离

typedefclassHASH
{
public:
intpi;//保存c[i][j]的行地址c[i]的下标i
classHASH*next;
HASH()
{
next=0;
}
}HashTable;

HashTable*hash[mod];

/*检查c[ai][]与c[bi][]是否对应列相等*/
boolcmp(intai,intbi)
{
for(intj=0;j<K;j++)
if(c[ai][j]!=c[bi][j])
returnfalse;
returntrue;
}

voidHash(intci)
{
intkey=0;//生成关键字
for(intj=1;j<K;j++)
key+=c[ci][j]*j;
key=abs(key)%mod;//由于c[][]有正有负,因此key值可能为负数

if(!hash[key])//新key
{
HashTable*pn=newHashTable;

pn->pi=ci;
hash[key]=pn;
}
else//key值冲突
{
HashTable*pn=hash[key];

if(cmp(pn->pi,ci))
{
intdist=ci-(pn->pi);
if(MaxLen<dist)
MaxLen=dist;
return;//由于pi与ci对应列数字相等,且pi地址必定比ci小
}//而要求的是最大距离,因此不需要保存ci,判断距离后直接返回
else
{
while(pn->next)
{
if(cmp(pn->next->pi,ci))
{
intdist=ci-(pn->next->pi);
if(MaxLen<dist)
MaxLen=dist;
return;
}
pn=pn->next;
}

//地址冲突但c[][]各列的值不完全相同

HashTable*temp=newHashTable;
temp->pi=ci;
pn->next=temp;
}
}
return;
}

intmain(void)
{
freopen("in.txt","r",stdin);
while(cin>>N>>K)
{
/*Initial*/

for(intp=0;p<K;p++)
{
c[0][p]=0;//第0只牛的特征默认为全0
sum[0][p]=0;
}

memset(hash,0,sizeof(hash));
Hash(0);//把第0只牛先放入哈希表
MaxLen=0;

/*Input*/

for(inti=1;i<=N;i++)
{
intDexf;//十进制特征数
cin>>Dexf;

for(intj=0;j<K;j++)
{
feature[i][j]=Dexf%2;//Dexf转换为逆序二进制
Dexf/=2;

sum[i][j]=sum[i-1][j]+feature[i][j];
c[i][j]=sum[i][j]-sum[i][0];
}

Hash(i);
}

/*Output*/

cout<<MaxLen<<endl;
}
return0;
}


SampleInput

73
7
6
7
2
1
4
2

73
7777777

44
1
2
4
8

44
8
1
2
4

54
3
1
2
4
8

15
3

12
3

13
7

65
16
8
4
2
31

SampleOutput

4
7
4
4
4
0
1
1
2
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: