• poj2148


    题意:给出若干个没有公共面积的多边形,几个多边形可能属于同一个国家,要求给这个地图染色,同一个国家用相同的颜色,相邻国家不能用相同颜色。问最少需要多少种颜色。

    分析:计算几何+搜索。先判断哪些多边形是相邻的(这里只有一个公共点的不算相邻)。对于两个多边形,两两比较他们所有的边,看是否有重合部分。建好图后,枚举颜色数量(也可二分查找),并判断这些颜色是否可行。判断过程用搜索。搜索的方法是,n个点,第一层确定第一个点的颜色,第二层确定第二个点的颜色,以此类推,每次要向下递归前先判断当前染色是否产生冲突。而不是向二分图染色那样染搜相邻的点。

    #include <cstdio>
    #include <map>
    #include <cstring>
    #include <string>
    using namespace std;
    
    #define zero(x) (((x)>0?(x):-(x))<eps)
    #define eps 1.0E-8
    #define MAX_POINT_NUM 105
    #define MAX_POLYGON_NUM 105
    #define MAX_TERR_NUM 15
    
    int double_cmp(double a)
    {
        if (zero(a))
            return 0;
        return a > 0 ? 1 : -1;
    }
    
    struct Edge
    {
        int v;
        int length;
        Edge()
        {}
        Edge(int v, int length):v(v), length(length)
        {}
    };
    
    struct Point
    {
        double    x,y;
        Point()
        {}
        Point(double x, double y):x(x), y(y)
        {}
        Point operator - (const Point &a) const
        {
            return Point(x - a.x, y - a.y);
        }
        bool operator == (const Point &a) const
        {
            return x == a.x && y == a.y;
        }
    };
    
    double cross_product(Point a, Point b)
    {
        return a.x * b.y - b.x * a.y;
    }
    
    double cross_product(Point p0, Point p1, Point p2)
    {
        return cross_product(p1 - p0, p2 - p0);
    }
    
    double dot_product(Point a, Point b)
    {
        return a.x * b.x + a.y * b.y;
    }
    
    double dot_product(Point p0, Point p1, Point p2)
    {
        return dot_product(p1 - p0, p2 - p0);
    }
    
    struct Line
    {
        Point a, b;
        Line()
        {}
        Line(Point a, Point b):a(a), b(b)
        {}
        bool operator == (const Line &l) const
        {
            return l.a == a && l.b == b;
        }
    };
    
    bool points_inline(Point p1, Point p2, Point p3)
    {
        return zero(cross_product(p1, p2, p3));
    }
    
    bool same_side(Point p1, Point p2, Line l)
    {
        return cross_product(l.a, p1, l.b) * cross_product(l.a, p2, l.b) > eps;
    }
    
    bool point_online_in(Point p, Line l)
    {
        return zero(cross_product(p, l.a, l.b)) && double_cmp(dot_product(p, l.a, l.b)) < 0;
    }
    
    bool overlap(Line u, Line v)
    {
        if (u == v || (u.a == v.b && u.b == v.a))
            return true;
        if (!points_inline(u.a, u.b, v.a) || !points_inline(u.a, u.b, v.b))
            return false;
        bool ret = point_online_in(u.a, v);
        ret = ret || point_online_in(u.b, v);
        ret = ret || point_online_in(v.a, u);
        ret = ret || point_online_in(v.b, u);
        return ret;
    }
    
    struct Polygon
    {
        Point point[MAX_POINT_NUM];
        int id;
        int point_num;
    }polygon[MAX_POLYGON_NUM];
    
    map<string, int> territory_id;
    int polygon_num;
    int territory_cnt;
    int color[MAX_POLYGON_NUM];
    bool graph[MAX_TERR_NUM][MAX_TERR_NUM];
    
    void input()
    {
        territory_id.clear();
        territory_cnt = 0;
        for (int i = 0; i < polygon_num; i++)
        {
            char territory_name[25];
            scanf("%s", territory_name);
            string name = string(territory_name);
            if (territory_id.find(name) == territory_id.end())
            {
                territory_id[name] = ++territory_cnt;
            }
            polygon[i].point_num = 0;
            polygon[i].id = territory_id[name];
            while (1)
            {
                int j = polygon[i].point_num;
                scanf("%lf", &polygon[i].point[j].x); 
                if (polygon[i].point[j].x == -1)
                    break;
                scanf("%lf", &polygon[i].point[j].y); 
                polygon[i].point_num++;
            }
        }
    }
    
    bool neighbour(Polygon &a, Polygon &b)
    {
        for (int i = 0; i < a.point_num; i++)
        {
            for (int j = 0; j < b.point_num; j++)
            {
                Line l1 = Line(a.point[i], a.point[(i + 1) % a.point_num]);
                Line l2 = Line(b.point[j], b.point[(j + 1) % b.point_num]);
                if (overlap(l1, l2))
                    return true;
            }
        }
        return false;
    }
    
    void create_graph()
    {
        memset(graph, 0, sizeof(graph));
        for (int i = 0; i < polygon_num - 1; i++)
        {
            for (int j = i + 1; j < polygon_num; j++)
            {
                int a = polygon[i].id;
                int b = polygon[j].id;
                a--;
                b--;
                if (a == b || graph[a][b])
                    continue;
                if (neighbour(polygon[i], polygon[j]))
                    graph[a][b] = graph[b][a] = true;
            }
        }
    }
    
    bool ok(int u)
    {
        for (int i = 0; i < territory_cnt; i++)
            if (i != u && graph[i][u])
            {
                if (color[u] == color[i])
                    return false;
            }
        return true;
    }
    
    bool dfs(int color_num, int u)
    {
        if (u == territory_cnt)
        {
            return true;
        }
        for (int i = 0; i < color_num; i++)
        {
            color[u] = i;
            if (!ok(u))
                continue;
            if (dfs(color_num, u + 1))
                return true;
        }
        color[u] = -1;
        return false;
    }
    
    int main()
    {
        while (scanf("%d", &polygon_num), polygon_num)
        {
            input();
            create_graph();
            int ans = 0;
            while (ans <= 10)
            {
                ans++;
                memset(color, -1, sizeof(color));
                color[0] = 0;
                if (dfs(ans, 1))
                {
                    printf("%d
    ", ans);
                    break;
                }
            }
        }
        return 0;
    }
    View Code
  • 相关阅读:
    VS2010/MFC编程入门之三(VS2010应用程序工程中文件的组成结构)
    VS2010/MFC编程入门之二(利用MFC向导生成单文档应用程序框架)
    VS2010/MFC编程入门之一(VS2010与MSDN安装过程图解)
    Getmemory问题
    计算后缀表达式
    0-1背包问题
    不抛异常的swap函数
    输出n*n矩阵
    字符串全排列输出
    判断主机字节
  • 原文地址:https://www.cnblogs.com/rainydays/p/3320274.html
Copyright © 2020-2023  润新知