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
原文地址:https://www.cnblogs.com/rainydays/p/3320274.html