Online Judge | Problem Set | Authors | Online Contests | User | ||||||
---|---|---|---|---|---|---|---|---|---|---|
Web Board Home Page F.A.Qs Statistical Charts | Current Contest Past Contests Scheduled Contests Award Contest |
"使用VMWare虚拟机。但是发现一个可怕的事情:虚拟机中文件无法 > 复制到物理机上。怎么办呢?" ----用virtualbox的“共享数据空间”。In Reply To:雁过留声——小记在Linux下写程序 Posted by:fanhqme at 2009-11-08 11:39:30 > 听说NOIP要用NOILinux,我马不停蹄的开始了适应。 > 之所以用这题来练手,主要因为它比较简单...但是,想AC不容易。 > > 安装NOILinux不是一个容易事,我采取了一个妥协的方法: > 使用VMWare虚拟机。但是发现一个可怕的事情:虚拟机中文件无法 > 复制到物理机上。怎么办呢? > 再次妥协:让虚拟机使用软盘,再用WinImage读取。 > > 上次比赛时听说几个IDE均出现了问题,我就用gedit+g+++gdb来写程序 > > gedit 3246.cpp 编辑 > g++ 3246.cpp -o 3246 -Wall 编译,-Wall生成所有警告,挺实用的 > ./3246 运行 > g++ 3246.cpp -o 3246 -Wall -g -g生成调试信息 > gdb 3246 调试 > > 首先说说这题算法: > 用GrahamScan扫描求出一个凸包,然后对每个凸包上的点: > 去除它, > 设凸包上它的前驱与后继为x,y, > 把极角排序后位于x与y之间的点求个凸包, > 计算面积。 > > 问题一般出在移除最左下的那个“基准”点上,我的策略: > 删了它,重新求凸包。 > > 计算几何貌似是从来不卡常数的(也许有例外),于是我就写的比较工程, > 判断方向、面积、排序都单独用比较一般的函数实现 > int Direction(int i,int j,int k){ > long long t=(X[j]-X[i])*(Y[k]-Y[i])-(X[k]-X[i])*(Y[j]-Y[i]); > if (t>0)return 1; > if (t==0)return 0; > return -1; > } > long long Dist(int a,int b){ > return (X[a]-X[b])*(X[a]-X[b])+(Y[a]-Y[b])*(Y[a]-Y[b]); > } > long long area(int a,int b){ > long long s=((X[a]-X[0])*(Y[b]-Y[0])-(X[b]-X[0])*(Y[a]-Y[0])); > if (s<0)s=-s; > return s; > } > void exchange(int a,int b){ > long long t; > t=X[a];X[a]=X[b];X[b]=t; > t=Y[a];Y[a]=Y[b];Y[b]=t; > } > void qs(int b,int e){ > if (b>=e)return; > exchange(b,(b+e)>>1); > int j; > for (int i=j=b+1;i<=e;i++)if (Direction(0,i,b)==1 || > Direction(0,i,b)==0 && Dist(0,i)<Dist(0,b)) > exchange(i,j++); > exchange(--j,b); > qs(b,j-1);qs(j+1,e); > } > > 剩下的扫描、主程序都比较简单了。 > 强烈提示wa的人:正确处理共线是一个AC的凸包的一半。 > long long Scan(int b,int e,int *buf,int &m,int delta=-1){ > //delta这个点在扫描的时候将被忽略,相当于被删除 > m=1;buf[0]=0; > for (int i=b;i<=e;i++)if (i!=delta){ > buf[m++]=i; > while (m>3 && Direction(buf[m-2],buf[m-1],buf[m-3])==-1) > buf[m-2]=buf[m-1],m--; > } > long long r; > r=0; > for (int i=1;i<m-1;i++)r+=area(buf[i],buf[i+1]); > return r; > } > > 看一眼数据规模,是要用long long的。 > 这时候,一个很纠结的问题出现了: > 如何输出long long?用哪种方式? > printf("%lld",a)//for Linux > printf("%I64d",a)//for POJ > cout<<a//...it's too slow > 这个问题让我思考了很久,最终决定:自己写一个输出函数 > void printll_(long long a){ > if (a!=0){ > printll_(a/(long long)10); > printf("%d",int(a%(long long)10)); > } > } > void printll(long long a){ > if (a==0)printf("0"); > else if (a>0)printll_(a); > else if (a<0){ > putchar('-'); > printll(-a); > } > } > > 写好了,交上去,挂了。 > 怎么办? > 随便编几个数据: > 4 0 0 0 1 1 0 1 1 > 16 0 0 0 1 0 2 0 3 1 0 1 1 1 2 1 3 2 0 2 1 2 2 2 3 3 0 3 1 3 2 3 3 > 4 0 0 100 0 1 0 1 1 > 4 0 0 100 0 0 1 1 1 > 4 0 0 0 100 1 0 1 1 > 4 0 0 1 0 0 1 100 100 > 结果,跑第三个数据的时候,输出49.50 > 赶紧调试,一想到有一个叫gdb的好东西,就不用自己的土鳖调试法了。 > (gdb)break 84 > (gdb)print a2 > ...... > 一直追踪到最后输出结果部分都是正确的。 > 在一看代码: > printll(a2/(long long)2); > 怪不得,打错变量了。 > printll(ret/(long long)2); > 改,运行。 > 然而,最后一组数据挂了。 > 接着追踪,愕然发现:调用Scan忘记设置delta了。 > 接着修改,通过软盘拷贝出,提交...终于AC啦! > > 说一下用Linux我的几个习惯: > 它有一个切换桌面的功能,于是,我就把系统管理、编程的窗口分到两个桌面上, > 免去了很多麻烦! > 编译、运行、调试都要用不同的命令,都挺长的......我就 > 各开一个终端,再次操作的时候按↑键再回车就可以了。 > gdb真是个好东西!使用它可以让工作量大大降低。 > 不过,它在windows下的各个IDE中表现貌似很惨。 Followed by:
Post your reply here: |
All Rights Reserved 2003-2013 Ying Fuchen,Xu Pengcheng,Xie Di
Any problem, Please Contact Administrator