主题:第40次编程比赛结果
neverPE [专家分:1620] 发布于 2006-09-03 22:12:00
第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 楼
rickone [专家分:15390] 发布于 2006-09-03 21:17:00
哦,看到了,标程用的递归很妙啊,把整个查寻线路上的结点都往根上靠了,不错不错,我的程序一次查询只把查的结点往根靠,效率低一些
12 楼
neverPE [专家分:1620] 发布于 2006-09-03 21:27:00
To 8楼boxertony:测试数据就是第1轮我给出的,你的程序通过前面几个,然后就异常中止。我的意思是Runtime Error,当时想到可能是内存,就写错了,笔误。
你测试那些数据没问题?
13 楼
boxertony [专家分:23030] 发布于 2006-09-03 21:34:00
// 下面是我根据你写的代码写的测试函数。不知哪儿没有理解到,结果不对啊,所有结果都是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 楼
BigCarrot [专家分:10] 发布于 2006-09-03 21:42:00
neverPE 你确信是在release模式下测的吗?
我看了一下iAkiak的代码,应该不会有3倍的差距
关于测试的问题,在上一次比赛结果中我已经提到过了
这次我特意避免了函数调用,实际上这是个很不好的习惯
delete确实是忘了 :(
不过对这种一次性的调用没什么影响
如果要在一次运行中测试多组数据,那这个程序就死菜了
15 楼
neverPE [专家分:1620] 发布于 2006-09-03 21:42:00
是我没有说清楚,第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 楼
boxertony [专家分:23030] 发布于 2006-09-03 21:52:00
不好意思,还是没有理解你的意思。下面这样改了,所有结果都是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 楼
neverPE [专家分:1620] 发布于 2006-09-03 21:55:00
To 14楼:你认为不会有3倍差距,是你自己的感觉,还是经过测试?
不要认为是函数调用带来的问题,我重复9楼说过的话,你看看我给的参考程序,频繁的函数调用,而且是递归,但并不比你的程序慢。
18 楼
wshong [专家分:1880] 发布于 2006-09-03 21:57:00
>10s是什么意思啊?唉!又一次失败!!!
19 楼
neverPE [专家分:1620] 发布于 2006-09-03 22:14:00
To 16楼boxertony:不好意思,我一直没说清楚。刚才改了帖子里的描述。现在应该没问题了。你那样生成的数据,1是正确的答案。你的程序结果一直都是正确的。n=50000的时候可以出解吗?
To 18楼wshong:>10s就是说,程序运行10秒还没有出结果。
20 楼
boxertony [专家分:23030] 发布于 2006-09-03 22:24:00
谢谢。终于搞清楚了,当n很大时,我的程序由于递归深度太大而发生栈溢出了。
我来回复