O興~
 
« 上一篇: 凸多边形的重心 下一篇: N * logN的最大上升子序列(附标程) »
我很懒的 @ 2006-08-24 22:36

今天做了一道求一个多边形是否存在对称轴的题。主要是要想到一点:如果有对称轴,则对称轴左、右两边的顶点数应该相等,并且两两对称。所以对称轴肯定经过某一顶点或某一条边的中点。具体分两种情况:如果多边形的顶点数为奇数,则对称轴肯过经过一个顶点和它对边的中点;如果多边形的顶点数为偶数,则对称轴要么过两个顶点,要么过两条对边的中点。
原题在UVA10416(online-judge.uva.es/p/v104/10416.html),是刘汝佳出的哦。

应陈力的要求,我把代码贴在这里。写得有点乱。其实还可以写得再好看一点。只要把每条边的中点也加到多边形中,那么就只有一种情况,就是总共有偶数个顶点,对称轴一定过某两个顶点。
#include <iostream>

using namespace std;

//<reused_codes>
struct XY;

inline double crsProd(const XY&, const XY&);
inline double dotProd(const XY&, const XY&);

//A 2-dimensional point or vector.
struct XY {
    double x;
    double y;

    void set(double _x, double _y) {
        x = _x;
        y = _y;
    }

    XY operator - (const XY& other) const {
        XY result = {x - other.x, y - other.y};
        return result;
    }

    XY operator + (const XY& other) const {
        XY result = {x + other.x, y + other.y};
        return result;
    }

    XY operator / (double d) const {
        XY result = {x / d, y / d};
        return result;
    }

    //Square of the length of this vector. Sometimes you just want to compare
    //the lengths of two vectors, so you needn't calculate the square roots.
    double normSqr() const {
        return x * x + y * y;
    }
};

//Cross product of vector a and b
inline double crsProd(const XY& a, const XY& b) {
    return a.x * b.y - b.x * a.y;
}

//Dot product of vector a and b
inline double dotProd(const XY& a, const XY& b) {
    return a.x * b.x + a.y * b.y;
}

//Whether point a and b are symmetric about line (axis1, axis2).
bool isSymm(const XY& a, const XY& b, const XY& axis1, const XY& axis2) {
    return dotProd(a - b, axis1 - axis2) == 0.0
           && (a - axis1).normSqr() == (b - axis1).normSqr();
}
//</reused_codes>


const int MAX_POINT = 100;

XY g_point[MAX_POINT];
int g_pntCnt;

bool solveEven() {
    bool symm = false;
    int halfCnt = g_pntCnt / 2;
    for (int i = 0; i < halfCnt && !symm; i++) {
        symm = true;
        XY axis1 = g_point[i];
        XY axis2 = g_point[(i + halfCnt ) % g_pntCnt];
        for (int j = 1; j < halfCnt && symm; j++) {
            XY left = g_point[(i + j) % g_pntCnt];
            XY right = g_point[(i + g_pntCnt - j) % g_pntCnt];
            if (!isSymm(left, right, axis1, axis2)) {
                symm = false;
            }
        }
        if (!symm) {
            symm = true;
            XY axis1 = (g_point[i] + g_point[(i + 1) % g_pntCnt]) / 2.0;
            XY axis2 = (g_point[(i + halfCnt) % g_pntCnt]
                        + g_point[(i + halfCnt + 1) % g_pntCnt]
                       ) / 2.0;
            for (int j = 1; j < halfCnt && symm; j++) {
                XY left = g_point[(i + j) % g_pntCnt];
                XY right = g_point[(i + g_pntCnt - j + 1) % g_pntCnt];
                if (!isSymm(left, right, axis1, axis2)) {
                    symm = false;
                }
            }
        }
    }
    return symm;
}

bool solveOdd() {
    bool symm = false;
    int halfCnt = g_pntCnt / 2;
    for (int i = 0; i < g_pntCnt && !symm; i++) {
        symm = true;
        XY axis1 = g_point[i];
        XY axis2 = (g_point[(i + halfCnt) % g_pntCnt]
                    + g_point[(i + halfCnt + 1) % g_pntCnt]
                   ) / 2.0;
        for (int j = 1; j <= halfCnt && symm; j++) {
            XY left = g_point[(i + j) % g_pntCnt];
            XY right = g_point[(i + g_pntCnt - j) % g_pntCnt];
            if (!isSymm(left, right, axis1, axis2)) {
                symm = false;
            }
        }
    }
    return symm;
}

void solve() {
    bool symm;
    if (g_pntCnt % 2 == 0) {
        symm = solveEven();
    }
    else {
        symm = solveOdd();
    }
    if (symm) {
        cout << "Yes" << endl;
    }
    else {
        cout << "No" << endl;
    }
}

void input() {
    cin >> g_pntCnt;
    for (int i = 0; i < g_pntCnt; i++) {
        cin >> g_point[i].x >> g_point[i].y;
    }
}

int main() {
    int caseCnt;
    cin >> caseCnt;
    for (int i = 0; i < caseCnt; i++) {
        input();
        solve();
    }
    return 0;
}



最新评论


陈力

2006-10-09 00:51

能否借你这道题的代码一看,最近正看计算几何

可以,我已经贴上来了。

评论 / 个人网页 / 扔小纸条
* 昵称

已经注册过? 请登录

新用户请先注册 以便能显示头像及追踪评论回复

Email
网址
* 评论
表情
 


 

分类小组论坛
杂谈 , 娱乐、八卦 , 文学、艺术 , 体育 , 旅游、同城 , 象牙塔 , 情感 , 时尚、生活 , 星座 , 科技

请注意遵守中华人民共和国法律法规, 如威胁到本站生存, 将依法向有关部门报告, 同时本站的相关记录可能成为对您不利的证据.

相关法律法规
全国人大常委会关于维护互联网安全的决定
中华人民共和国计算机信息系统安全保护条例
中华人民共和国计算机信息网络国际联网管理暂行规定
计算机信息网络国际联网安全保护管理办法
计算机信息系统国际联网保密管理规定

日历
网志分类
· 所有网志
· program
· 未分类
站内搜索
友情链接
· 歪酷博客
· 管理我的Blog
· jamie
· feemi
· lyrist
· tata
· allen
· richard

订阅 RSS

0081325

歪酷博客