usotsuki

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

poj3349

#include<stdio.h>
#include<algorithm>
#include<string.h>
using namespace std;
int ad[100000][6],hd[100003],n,el,flag;
struct S
{
    int p[6];
    bool operator < (const S &a)const
    {
        int i;
        for(i=0;i<6;i++)
		{
				if(p[i]<a.p[i])return 1;
				else if(p[i]>a.p[i])return 0;
		}
        return 1;
    }
}s[12];
struct E
{
    int v,p;
}e[100000];
inline void adde(int u,int v)
{
    e[el].v=v,e[el].p=hd[u],hd[u]=el++;
}
void adjust(int n)
{
    int i,j,min=0;
    for(i=0;i<6;i++)
    {
        for(j=0;j<6;j++)
        {
            s[i].p[j]=ad[n][(i+j)%6];
        }
    }
    for(i=0;i<6;i++)
    {
        for(j=0;j<6;j++)
        {
            s[i+6].p[j]=ad[n][(i-j+6)%6];
        }
    }
    for(i=0;i<12;i++)
		if(s[i]<s[min])min=i;
    for(i=0;i<6;i++)
        ad[n][i]=s[min].p[i];
}
inline bool same(int x,int y)
{
    int i;
    for(i=0;i<6;i++)
        if(ad[x][i]!=ad[y][i])
			return 0;
    return 1;
}
inline void hash(int n)
{
    int i=0,j,k;
    for(j=0;j<6;j++)
    {
        i+=ad[n][j]*(j+1),i%=100003;
    }
    for(k=hd[i];k!=-1;k=e[k].p)
    {
        if(same(k,n)) flag=1;
    }
    adde(i,n);
}
int main()
{
    int i,j,k;
    while(~scanf("%d",&n))
    {
        memset(hd,-1,sizeof(hd));
        el=0,flag=0;
        for(i=0;i<n;i++)
        {
            for(j=0;j<6;j++)
                scanf("%d",&ad[i][j]),ad[i][j]%=100003;
            if(!flag)
            {
				adjust(i);
				hash(i);
			}
        }
        if(flag)printf("Twin snowflakes found.\n");
        else printf("No two snowflakes are alike.\n");
    }
    return 0;
}

 一开始使用的hash函数为平方和,但是始终会出现tle,经过多次试验把hash函数改为现在的样子后ac,看之前的代码:

void hash(int n)
{
    int i=0,j,k;
    for(j=0;j<6;j++)
    {
        i+=(ad[n][j]+j)*(ad[n][j]+j),i%=100003;
    }
    for(k=hd[i];k!=-1;k=e[k].p)
    {
        if(same(k,n)) flag=1;
    }
    adde(i,n);
}

 对比ac之后的代码,开始的时候认为是两倍的访存时间导致了TLE,后来又实验了:

inline void hash(int n)
{
    int i=0,j,k;
    for(j=0;j<6;j++)
    {
        k=ad[n][j]+j;
        i+=k*k,i%=100003;
    }
    for(k=hd[i];k!=-1;k=e[k].p)
    {
        if(same(k,n)) flag=1;
    }
    adde(i,n);
}

 仍然TLE,我就回想到了gcc的优化问题 在之前一次的貌似两倍访存会被优化为一次访存,但是计算部分仍然是乘法运算,因为要计算平方的数可能很大,而后的代码中的乘法是乘以一个常量的,

在gcc优化的时候会使用LEA指令来进行乘法运算,时间会节省很多。

posted on 2013-09-22 09:32  usotsuki  阅读(166)  评论(0)    收藏  举报