代码改变世界

数组的一个小优化技巧

2009-05-08 05:53  Logic0  阅读(310)  评论(0编辑  收藏  举报
我顶 字号:

http://acm.pku.edu.cn/JudgeOnline/problem?id=2443

 

TLE的代码:

#include <stdio.h>

#include <string.h>

#include <stdlib.h>

bool num[1003][10010];



int main()

{

    int n,m;

    int i,j,k,tmp,p,q;

    scanf("%d",&n);

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

        {

            scanf("%d",&m);

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

            {

                scanf("%d",&tmp);

                num[i][tmp] = 1;

            }

        }

        scanf("%d",&m);

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

        {

            scanf("%d%d",&i,&j);

            for(q=0 ; q<n ; q++)

            {

                if(num[q][i] && num[q][j])

                {

                    printf("Yes\n");

                    break;

                }

            }

            if(q==n)

            {

                printf("No\n");

            }

        }

    return 0;

}

AC的代码:
#include <stdio.h>

#include <stdlib.h>

#include <string.h>



bool c[10010][1010];



int main()

{

int n,m,t,i,j,a,temp,g,k; 

bool flag;

memset(c,false,sizeof(c));

scanf("%d",&n);

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

{

   scanf("%d",&m);

   while(m--) { scanf("%d",&temp); c[temp][t]=true; }

}

scanf("%d",&k);

while(k--)

{

   scanf("%d%d",&i,&j);

   flag=true;

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

   { 

    if(c[i][g]&&c[j][g]) { printf("Yes\n"); flag=false; break; } 

   }

   if(flag) printf("No\n");

} 

return 0;

}



唯一的区别就在于数组的维数上:
b[1003][10010] 这样定义的时候是超时的。
b[10010][1003] 这样定义的时候是可以AC的。
 
具体区别正在研究中
 
//2009-5-8补充原因:
数据寻址的过程不同。
数组在intel机中是按行存储,每次将二维数组行地址放入基址寄存器,然后找到数据地址。
对于b[1003][10010],执行下列代码:
for(p=0 ; p<n ; p++)
{
    if(b[i][p] && b[j][p])
}
只需将行地址b[i]和b[j]存储即可,然后在以此行地址为首地址的一维数组内寻找数据。
而另外的方法则是每次都要重新计算行的首地址,并将其存入基址寄存器,再计算数据位置,相比来看操作要多于前者,在数据量大的时候就显现出其差别。
 
总结:
在定义数组的时候,如果可以,尽量将第一维设置为较小的。