回 帖 发 新 帖 刷新版面

主题:第40次编程比赛结果

第1题 主要是集合查询和合并。合并的效率很重要,如果能想到并查集,那么做起来就不难,代码量也不大。本来第1题想出图论的,又怕控制不好难度,不过并查集跟树挂钩,也勉强算是图论吧。给出一段代码供参考:
int root(int v,int* set)
{
    if (set[v] == v) return v;
    return set[v]=root(set[v],set);
}

int ReligionsStd(int n,int m,int* record)
{
    int i,count=n;
    int* set=new int[n+1];

    for (i=0;i<=n;i++) //初始化
        set[i]=i;
    for (i=0;i<m*2;i+=2)
        if (root(record[i],set)!=root(record[i+1],set))//如果属于不同集合
        {
            set[set[record[i]]]=set[record[i+1]];//合并
            count--;
        }

    delete[] set;
    return count;
}


  第1轮:
  fstream fout ("filename");
  n=50000;
  m = [color=FF0000]t[/color] -1;
  fout<<"1 2"<<endl;
  for (i=3;i <= [color=FF0000]t[/color];i+=2)
    fout<<i<<' '<<i+1<<endl<<i<<' '<<i-1<<endl;
  测试数据由上面的代码生成,[color=FF0000]t[/color]=20,200,2000,20000,50000,这是针对性的数据,如果集合合并效率不高,用这组数据是很痛苦的。本来只是是想测试速度,但很多人的程序都出错了。正确结果依次是49981,49801,48001,30001,1。

1 jackin0627: >10s
2 天边蓝:错误
3 iAkiak: 47ms 
5 liyanguestc: 错误 
6 joekings:0ms
7 liangbch:错误
8 Cyre:错误
10 yelv:错误
11 joekings: 0ms
12 zheni: 7922ms
13 xiaopangzi:错误
14 wlsss: >10s
15 BigCarrot: <15ms
16 rickone: <15ms
17 孤独的猫:>10s
18 boxertony:Runtime Error
19 NingYusui:错误
20 xyhx:错误
21 eastcowboy:0ms
22 babyzn:错误
23 jfs771:错误
24 hwjian:错误
25 火海时代:错误
26 wshong:>10s

第2轮:
joekings和eastcowboy的程序快的出奇,但很遗憾算法不对。用一组简单的数据可以测出错误。
n=3 m=2
record={1 3 2 3}

第3轮:
12 zheni: >10s
3 iAkiak: 100ms 
15 BigCarrot: 37ms
16 rickone: 68ms
多组数据测试,以上3位算法没有本质的差别,但BigCarrot实现的最快。iAkiak用模板在速度上可能有些吃亏。



第2题:第2题是简单博弈论题,实现起来很方便,大家做的正确率也很高。
2 boxertony:0ms
3 joekings:0ms
6 liyanguestc:0ms
7 BigCarrot:0ms
8 孤独的猫:0ms
9 wlsss:0ms
14 forjane:0ms
17 xyhx:0ms

5 ITER:错误
10 hainanlion:错误
11 hwjian: 错误(30位,longlong不够)
12 magicalking:错误 long更不够
13 liangbch:超时


综合以上2题的结果,第40次编程比赛的冠军是[color=FF0000]BigCarrot[/color],恭喜他。

如果对测试结果有任何异议,请尽快跟帖,我会认真复查。

回复列表 (共44个回复)

11 楼

哦,看到了,标程用的递归很妙啊,把整个查寻线路上的结点都往根上靠了,不错不错,我的程序一次查询只把查的结点往根靠,效率低一些

12 楼

To 8楼boxertony:测试数据就是第1轮我给出的,你的程序通过前面几个,然后就异常中止。我的意思是Runtime Error,当时想到可能是内存,就写错了,笔误。

你测试那些数据没问题?

13 楼

// 下面是我根据你写的代码写的测试函数。不知哪儿没有理解到,结果不对啊,所有结果都是2。
int main()
{
    int        n, m;
    int        i;

    n = 50000;
    m=n-1;

    record[0] = n;
    record[1] = m;
    record[2] = 1;
    record[3] = 2;
    
    for (i=3;i<=n;i+=2)
    {
        record[i*2] = i;
        record[i*2+1] = i+1;
        record[i*2+2] = i;
        record[i*2+3] = i-1;
    }

    int    count;
    count = Religions(n, m, record);

    printf("count= %d\n", count);

    return 0;
}

14 楼

neverPE 你确信是在release模式下测的吗?
我看了一下iAkiak的代码,应该不会有3倍的差距

关于测试的问题,在上一次比赛结果中我已经提到过了

这次我特意避免了函数调用,实际上这是个很不好的习惯

delete确实是忘了 :(
不过对这种一次性的调用没什么影响
如果要在一次运行中测试多组数据,那这个程序就死菜了

15 楼

是我没有说清楚,第1行50000和n-1是n和m的值,“1 2”对应record[0] record[1]
之后依次对应record[2] record[3] ……
    fout<<"50000 "<<n-1<<endl<<"1 2"<<endl;
    for (i=3;i<=n;i+=2)
        fout<<i<<' '<<i+1<<endl<<i<<' '<<i-1<<endl;

16 楼

不好意思,还是没有理解你的意思。下面这样改了,所有结果都是1。
int main()
{
    int        n, m;
    int        i;

    n = 20;
    m = n-1;

    record[0] = 1;
    record[1] = 2;
    
    for (i=3;i<=n;i+=2)
    {
        record[i*2-4]   = i;
        record[i*2+1-4] = i+1;
        record[i*2+2-4] = i;
        record[i*2+3-4] = i-1;
    }

    int    count;
    count = Religions(n, m, record);

    printf("count= %d\n", count);

    return 0;
}

17 楼

To 14楼:你认为不会有3倍差距,是你自己的感觉,还是经过测试?
不要认为是函数调用带来的问题,我重复9楼说过的话,你看看我给的参考程序,频繁的函数调用,而且是递归,但并不比你的程序慢。

18 楼

>10s是什么意思啊?唉!又一次失败!!!

19 楼

To 16楼boxertony:不好意思,我一直没说清楚。刚才改了帖子里的描述。现在应该没问题了。你那样生成的数据,1是正确的答案。你的程序结果一直都是正确的。n=50000的时候可以出解吗?

To 18楼wshong:>10s就是说,程序运行10秒还没有出结果。

20 楼

谢谢。终于搞清楚了,当n很大时,我的程序由于递归深度太大而发生栈溢出了。

我来回复

您尚未登录,请登录后再回复。点此登录或注册