`
happmaoo
  • 浏览: 4430370 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

ACM UVa算法题209 Triangular Vertices的解法

阅读更多
<iframe align="top" marginwidth="0" marginheight="0" src="http://www.zealware.com/46860.html" frameborder="0" width="468" scrolling="no" height="60"></iframe>

有一段时间没有做ACM算法题目了,今天正好有空便随便挑了209题来做做:ACM UVa算法题#209

这道题有几个要点:

1. 给定坐标系

坐标系很容易定,我采用的是第一个点为(0, 0)点,X方向差别为2个单位,Y方向差别为1个单位,点之间的距离,也就是LEN1个单位,这样便于计算。注意我用的不是实际长度,而是抽象的单位,这个单位在不同方向上面意义不一样,否则很容易通过三角形相关公理推出这样的三角形不存在,我们关心的只是这样的一个对应关系。这里的人为设定确实有些Confusing,我之前也是按照一般的三角形的长度,如345来定义,但是后来发现这样做做的乘除法太多,过于浪费CPU Cycle,如果按照我这样的设定,大部分情况只用到加减法,另外一种情况只需用到移位操作即可。

参看下图:

<shapetype id="_x0000_t75" coordsize="21600,21600" o:spt="75" o:preferrelative="t" path="m@4@5l@4@11@9@11@9@5xe" filled="f" stroked="f"><stroke joinstyle="miter"></stroke><formulas><f eqn="if lineDrawn pixelLineWidth 0"></f><f eqn="sum @0 1 0"></f><f eqn="sum 0 0 @1"></f><f eqn="prod @2 1 2"></f><f eqn="prod @3 21600 pixelWidth"></f><f eqn="prod @3 21600 pixelHeight"></f><f eqn="sum @0 0 1"></f><f eqn="prod @6 1 2"></f><f eqn="prod @7 21600 pixelWidth"></f><f eqn="sum @8 21600 0"></f><f eqn="prod @7 21600 pixelHeight"></f><f eqn="sum @10 21600 0"></f></formulas><path o:extrusionok="f" gradientshapeok="t" o:connecttype="rect"></path><lock v:ext="edit" aspectratio="t"></lock></shapetype><shape id="_x0000_i1025" style="WIDTH: 273.75pt; HEIGHT: 219pt" type="#_x0000_t75" o:ole=""><imagedata src="file:///C:%5CUsers%5CATField%5CAppData%5CLocal%5CTemp%5Cmsohtmlclip1%5C01%5Cclip_image001.emz" o:title=""></imagedata></shape>

2. 判断是否两点连线是一条边(Coincide)

这里可以分两种情况:

a. Y1 = y2, 必然是Coincide

b. 否则,X_Delta = abs(x1 – x2), Y_Delta = abs(y1 – y2), 由于之前我们人为设定X方向差别为2个单位,Y方向差别为1一个单位,因此只要X_Delta = Y_Delta即可

3. 计算距离

假定是Coincide的情况,否则直接返回出错,因为在非Coincide的情况无需计算距离。此外,由于这里已经知道是Coincide,并且我们并没有统一单位,所以这里不能也不应该用勾股定理来计算长度,而是采用比例的方法,同样分两种情况,参考上图:

a. Y1 = y2, 那么因为X方向上两个单位对应一个长度Unit,所以长度=abs(x1 – x2) >> 1;

b. 否则,长度Unit的个数和X/Y方向(任意)的差别相等,也就是长度=abs(x1 – x2)

4. 判断是否是目标图形,并且每条边相等

对于三角形,很简单,直接对3条边判断即可,没有什么变数。对于四边形和六边形就不同了,需要用到遍历来确定一个从某点开始(我们可以固定为第一个点)遍历所有点最后回到该点的环,并且每条边长度均相等,注意这里由于题目的特殊性,不用判断平行等条件。可以用一个邻接矩阵来代表对应的边的长度,这个应该一次性计算出来,如果非Coincide则设置为某个特殊值,比如0

刚开始提交的时候,Rank45,之后我又做了下面的优化:

1. 当遍历尝试完毕从最初点出发的某条边的时候,说明这一边不可能成为环,将其置为0表示不可通,并且遍历从最初点出发的其他同样长度的边,置为0,减少遍历次数

2. 在初始化计算所有点的坐标的时候改变了一点点算法,用加减法代替乘法

3. 最初坐标采用的是实际的长度,而不是像上面那样用不同的抽象单位算出,修改之后减少了大量乘除法计算

4. 调整遍历算法,由于从初始点出发之后,后3个点必然不能是初始点,因此做了一点修改对这个情况作了优化

5. 修改对邻接矩阵的算法,由于adj[i][j] = adj[j][i],所以只需计算矩阵的一半即可

修改之后再提交Rank变成了33,似乎是目前个人的最好纪录 J

32

0.170

792

LittleJohn Yo

C

2002-02-04 07:02:47

732386

33

0.172

1160

Yi Zhang

C++

2007-05-02 16:05:54

5551868

34

0.174

404

Rodrigo Malta Schmidt

C

2001-08-30 08:46:54

539862

代码如下:
//
//ACMUVaProblem#209
//http://acm.uva.es/p/v2/209.html
//
//Author:ATField
//Email:atfield_zhang@hotmail.com
//

#include
stdio.h>
#include
stdlib.h>
#include
string.h>

#defineMAX65535

structpoint
...{
public:
boolis_coincide(constpoint&pt)const
...{
//notallowtestingpointswithsamecoordinates
if(_x==pt._x&&_y==pt._y)
returnfalse;

if(_y==pt._y)
returntrue;
else
...{
intk1=abs(_x-pt._x);
intk2=abs(_y-pt._y);

if(k1==k2)
returntrue;
}


returnfalse;
}


intget_dist(constpoint&pt)const
...{
//notallowtestingpointswithsamecoordinates
if(_x==pt._x&&_y==pt._y)
return0;

if(_y==pt._y)
returnabs(_x-pt._x)>>1;//needtodivideby2
else
...{
intk1=abs(_x-pt._x);
intk2=abs(_y-pt._y);

if(k1==k2)
returnk1;
}


return0;
}


public:
staticconstintX_DELTA=2;
staticconstintY_DELTA=3;
staticconstintLEN=4;

public:
int_x;
int_y;
int_valid;

private:
staticpoints_all_points[MAX];

public:
staticvoidprepare()
...{
intlevel=0;
intbefore_next_level=1;
intnext_x=0;
intnext_y=0;

for(inti=1;iMAX;++i)
...{
s_all_points[i]._x
=next_x;
s_all_points[i]._y
=next_y;
before_next_level
--;

if(before_next_level==0)
...{
level
++;
before_next_level
=level+1;
next_x
=-level;
next_y
++;
}

else
next_x
+=2;

}



}


staticpoint*all_points()
...{
returns_all_points;
}

}
;

pointpoint::s_all_points[MAX];

boolcheck_triangle(int*n)
...{
//1.Duplicates
//Noneedtocheckduplicatebecausethefollowingcheckswilldo

//2.Coincide
//Checkeveryedge
point*points=point::all_points();
if(points[n[0]].is_coincide(points[n[1]])&&
points[n[
0]].is_coincide(points[n[2]])&&
points[n[
1]].is_coincide(points[n[2]]))
...{
//3.Samelength
//Checkeveryedge
intlen=points[n[0]].get_dist(points[n[1]]);
if(len==points[n[0]].get_dist(points[n[2]])&&
len
==points[n[1]].get_dist(points[n[2]]))
returntrue;
}


returnfalse;
}



boolinit_adj(int*n,intnum,intadj[6][6])
...{
point
*points=point::all_points();

for(inti=0;inum;++i)
...{
for(intj=i;jnum;++j)
...{
if(i==j)
...{
adj[i][j]
=0;
adj[j][i]
=0;
}

else
...{
//1.Duplicates
//Returnfalsewhenfoundduplicate
if(n[i]==n[j])
returnfalse;

//2.Coincide&Len(Whennotcoincide,len=0)
adj[i][j]=points[n[i]].get_dist(points[n[j]]);
adj[j][i]
=adj[i][j];
}

}

}



returntrue;
}


intfind_same_len_loop(intadj[6][6],intnum)
分享到:
评论

相关推荐

    ACM算法题100题-经典算法库

    根据给定文件的信息,我们可以提炼出与ACM算法题及经典算法库相关的多个知识点。以下是对这些知识点的详细解析: ### ACM国际大学生软件大赛简介 ACM(Association for Computing Machinery)国际大学生软件大赛是...

    acm分治算法acm分治算法acm分治算法acm分治算法

    学 习a c m 分 治算法 的入门 教程简单易学acm分治算法acm分治算法acm分治算法acm分治算法acm分治算法acm分治算法acm分治算法acm分治算法acm分治算法acm分治算法acm分治算法acm分治算法acm分治算法vacm分治算法acm...

    2016年ACM常用算法总结

    从给定的文件信息中,可以提取到关于ACM常用算法的知识点。ACM国际大学生程序设计竞赛(ACM International Collegiate Programming Contest,简称ACM-ICPC)是大学生计算机程序设计竞赛中最为著名的赛事之一,强调的...

    ACM常用算法(重要)

    ACM常用算法(重要)ACM常用算法(重要)ACM常用算法(重要)ACM常用算法(重要)ACM常用算法(重要)ACM常用算法(重要)ACM常用算法(重要)ACM常用算法(重要)ACM常用算法(重要)

    ACM练习题ACM各种练习题ACM各种练习题ACM各种练习题

    ACM各种练习题ACM各种练习题ACM各种练习题ACM各种练习题ACM各种练习题ACM各种练习题ACM各种练习题ACM各种练习题ACM各种练习题ACM各种练习题ACM各种练习题ACM各种练习题ACM各种练习题ACM各种练习题ACM各种练习题ACM...

    用于 ACM 的算法代码模板.zip

    用于 ACM 的算法代码模板.zip用于 ACM 的算法代码模板.zip用于 ACM 的算法代码模板.zip用于 ACM 的算法代码模板.zip用于 ACM 的算法代码模板.zip用于 ACM 的算法代码模板.zip用于 ACM 的算法代码模板.zip用于 ACM 的...

    ACM考试题 ACM程序设计

    ### ACM程序设计基础知识点 #### 一、ACM竞赛概览 - **组织机构与活动**: 本课程由东北林业大学陈宇老师负责,通过邮箱Lg_chenyu@yahoo.com.cn进行联系。课程的主要目的是介绍ACM程序设计的基础概念及入门技巧。 - ...

    ACM集训+真题+讲解+ACM集训+真题+讲解

    ACM集训+真题+讲解+算法+代码模板库+视频 ACM集训+真题+讲解+算法+代码模板库+视频 ACM集训+真题+讲解+算法+代码模板库+视频 ACM集训+真题+讲解+算法+代码模板库+视频 ACM集训+真题+讲解+算法+代码模板库+视频 ...

    acm 算法,习题及解题报告

    ACM(国际大学生程序设计竞赛,International Collegiate Programming Contest)是一项全球性的编程竞赛,旨在培养大学生的算法设计和问题解决能力。在这个压缩包中,包含了多种算法的习题和解题报告,对于深入理解...

    ACM算法题集 基础算法教案

    ACM题集中可能包括快速排序、归并排序、冒泡排序、插入排序、选择排序、堆排序以及希尔排序等经典算法,以及一些优化后的排序算法如三向切分快速排序和基数排序。 二、图论算法 图论在ACM比赛中占据着重要地位,...

    acm递归算法总结竞赛

    在ACM(国际大学生程序设计竞赛)中,递归算法是一种常见的解决问题的方法,它通过函数自身调用自身来实现问题的解决。递归的核心在于找到基本情况(base case),即可以直接求解的问题,以及每次递归调用时问题规模...

    acm 常用算法模板

    在ACM(国际大学生程序设计竞赛)中,掌握一套高效的算法模板是至关重要的。这个“acm常用算法模板”正是为了帮助ACM竞赛初学者快速上手和应对各种问题而准备的。它包含了多种常见的算法思路和代码实现,旨在提高...

    ACM经典算法!ACM经典算法!好东西 超好!贪心

    动态规划是一种用于解决多阶段决策过程最优化的数学方法,起源于20世纪50年代由美国数学家R.E. Bellman提出的最优化原理。...理解和掌握动态规划的概念及其应用,对于在ACM竞赛和其他算法挑战中取得好成绩至关重要。

    ACM国际大学生软件大赛,主要是考的些算法题,一些相关的软件比赛都是考的算法题,这些题目可以看看

    ACM国际大学生软件大赛,全称是ACM/ICPC(International Collegiate Programming Contest),是一项全球范围内的顶级编程竞赛,旨在提升大学生的计算机科学技能,尤其是算法设计与分析能力。这个大赛不仅仅是对参赛...

    ACM常用算法模板.html

    ACM常用算法模板.html

    算法竞赛入门经典(第二版) UVa原题 PDF版

    通过解决UVa原题,读者不仅可以提升编程技能,还能更好地理解算法的本质,为未来的学术研究或职业生涯打下坚实的基础。因此,这份PDF习题集的本地化版本,无疑为算法学习者提供了一个更加便捷和高效的练习环境。

    ACM主要算法介绍.docx

    图算法是 ACM 主要算法中的一种重要算法,包括图的深度优先遍历和广度优先遍历、最短路径算法、最小生成树算法、拓扑排序、二分图的最大匹配、最大流的增广路算法等。这些算法可以解决图论中的各种问题。 三、数据...

    ACM常用算法介绍 ACM常用算法介绍

    ACM常用算法介绍 在算法竞赛中,掌握常用的算法是非常重要的,以下是ACM常用算法的介绍: 一、数学问题 1. 精度计算——大数阶乘 在计算大数阶乘时,需要注意精度的问题,避免溢出或精度损失。可以使用高精度...

Global site tag (gtag.js) - Google Analytics