• ----:)欢迎访问源码网(:----
    • 首页
    • 博客
    • 学院
    • 下载
    • 论坛
    • 影视
    • 发布源码
    • RSS
    • ITPig
    • 笑话网
    • 百家姓
    • 繁體中文

源码网 - 中国第一源码门户
选择镜像:网通镜像 - 电信主站
  • 首 页
  • 新闻动态
  • 网站运营
  • 网页制作
  • WEB开发
  • 编程开发
  • 图像媒体
  • 操作系统
  • 数据库
  • 服务器
热门搜索 优化 SEO 故事 cms IIS7 MySQL 个人 AdSense 主题推广 | 文章搜索: 高级搜索
会员登录/控制面版您的位置: 学院首页 >> WEB开发 >> .NET 开发 >> 详细内容
 

推荐文章

 
 

热点文章

  • FckEditor远程图片下载插件
  • TFS(Team Foundation Server)使用经验
  • IIS过滤器实现.NET程序不破解DLL替换字符串一法
  • 为ASP.NET封装的SQL数据库访问类
  • ASP.NET2.0中文验证码的实现
  • Url地址重写,利用HttpHander手工编译页面并按需生成静..
  • ASP.NET学习笔记一——ASP和ASP.NET比较
  • 使用HtmlInputHidden 控件在本页面保持状态和跨页面传..
  • ASP.Net发邮件
  • Silverlight 2.0中文学习资源集萃
  • WinForm中使用XtraGrid控件,实现在界面中动态修改列显..
  • 解析ASP.NET木马文件操作
 
 

相关文章

  • 快算24的算法
  • ACM UVa 算法题 #202 - Repeating Decimals的解法
  • ACM UVa 算法题 #110 - Meta-Loopless Sort 的解法
  • ACM UVa 算法题 #108 - Maximum Sum的解法
  • ACM UVa 算法题 #507 - Jill Rides Again的解法
  • ACM UVa 算法题 #201 - Squares解法
  • ACM UVa 算法题 #200 - Rare Order的解法
  • ACM UVa 116 - Undirectional TSP的解法
  • ACM UVa 算法题100, 101, 103, 104, 112, 10405解法
  • 百度面试题(算法)
  • 张劲松:蚂蚁算法与SNS猜想
  • 获取 Google PR 代码Checksum 算法
 
 

百度搜索

 
 

ACM UVa算法题209 Triangular Vertices的解法

  • 阅览次数:
  • 文章来源: http://blog.csdn.net/ATField/
  • 原文作者: ATField
  • 整理日期: 2008-07-20
  • 发表评论
  • 字体大小:
  • 小
  • 中
  • 大

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

这道题有几个要点:

1.   给定坐标系

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

参看下图:

 

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

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

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

 
代码如下:
// 
// ACM UVa Problem #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>

#define MAX    65535

struct point
...{
public :
    
bool is_coincide(const point &pt) const
    
...{
        
// not allow testing points with same coordinates
        if( _x == pt._x && _y == pt._y )
            
return false;

        
if( _y == pt._y )
            
return true;
        
else
        
...{
            
int k1 = abs( _x - pt._x );
            
int k2 = abs( _y - pt._y );

            
if( k1 == k2 )
                
return true;
        }


        
return false;
    }


    
int get_dist(const point &pt) const
    
...{
        
// not allow testing points with same coordinates
        if( _x == pt._x && _y == pt._y )
            
return 0;

        
if( _y == pt._y )
            
return abs(_x - pt._x) >> 1;        // need to divide by 2
        else
        
...{
            
int k1 = abs( _x - pt._x );
            
int k2 = abs( _y - pt._y );

            
if( k1 == k2 )
                
return k1;
        }


        
return 0;
    }


public :
    
static const int X_DELTA = 2;
    
static const int Y_DELTA = 3;
    
static const int LEN = 4;

public :
    
int        _x;
    
int        _y;
    
int     _valid;

private :
    
static point s_all_points[MAX];

public :
    
static void prepare()
    
...{
        
int level = 0;
        
int before_next_level = 1;
        
int next_x = 0;
        
int next_y = 0;

        
for( int i = 1; i < MAX ; ++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;

        }



    }


    
static point *all_points()
    
...{
        
return s_all_points;
    }

}
;

point point::s_all_points[MAX];

bool check_triangle(int *n)
...{
    
// 1. Duplicates
    
// No need to check duplicate because the following checks will do

    
// 2. Coincide
    
// Check every edge
    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. Same length
        
// Check every edge
        int len = 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]]) )
            
return true;
    }


    
return false;
}



bool init_adj(int *n, int num, int adj[6][6])
...{
    point 
*points = point::all_points();

    
for( int i = 0; i < num; ++i )
    
...{
        
for( int j = i; j < num; ++j )
        
...{
            
if( i == j )
            
...{
                adj[i][j] 
= 0;
                adj[j][i] 
= 0;
            }

            
else
            
...{
                
// 1. Duplicates
                
// Return false when found duplicate
                if( n[i] == n[j] )
                    
return false;

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

        }

    }

        

    
return true;
}


int find_same_len_loop(int adj[6][6], int num)
...{
    
int stack[6];
    
int used[6];
    
int next[6];

    
for( int i = 1; i < num; ++i )
    
...{         
        
int len = adj[0][i];

        
// skip non-connected dots
        if( len == 0 ) continue;

        
// initialize "used" array & "next" array
        for( int j = 0; j < num; ++j )
        
...{
            used[j] 
= 0;
        }
        
        
        
int top = 0;
        stack[
0] = i;
        used[i] 
= 1;
        next[
0] = -1;

        top
++;

        
while( top > 0 )
        
...{
            next[top
-1]++;

            
// checked all the connected points?
            if( next[top-1] >= num )
            
...{
                
// yes, then pop the stack
                top--;
                used[stack[top]] 
= 0;
            }

            
else
            
...{
                
int next_point = next[top-1];

                
// follow non-used, same-length edge
                if( used[next_point] == 0 && len == adj[stack[top-1]][next_point] )
                
...{
                    stack[top] 
= next_point;
                    used[next_point] 
= 1;

                    
// don't allow pushing 0 into stack before the last point
                    if( top < num - 1 ) 
                        next[top] 
= 0;
                    
else
                        next[top] 
= -1;

                    top
++;

                    
// stack is full? found a loop
                    if( top == num )
                        
return len;
                }

            }

        }


        
// if this doesn't work, delete all edges starting from id 0 of this len
        for( int j = i; j < num; ++j )
            
if( adj[0][j] == len )
                adj[
0][j] = 0;
    }


    
return 0;
}


bool check_parallelogram(int *n)
...{
    
int adj[6][6];
    
if(!init_adj(n, 4, adj))
        
return false;           // found duplicate

    
if(find_same_len_loop(adj, 4))
        
return true;

    
return false;
}


bool check_hexagon(int *n)
...{
    
int adj[6][6];
    
if(!init_adj(n, 6, adj))
        
return false;           // found duplicate

    
if(find_same_len_loop(adj, 6))
        
return true;

    
return false;
}


int main(int argc, char *argv[])
...{
    point::prepare();
    
    
while(1)
    
...{
        
char input[255];
        
if( gets(input) == NULL )
            
break;
        
else if( strlen(input) == 0 )
            
break;
        
        
int n[6];
        
int fields = sscanf( input, "%d %d %d %d %d %d", &n[0], &n[1], &n[2], &n[3], &n[4], &n[5] );

        printf(
"