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

分析:计算几何+搜索。先判断哪些多边形是相邻的(这里只有一个公共点的不算相邻)。对于两个多边形,两两比较他们所有的边,看是否有重合部分。建好图后,枚举颜色数量(也可二分查找),并判断这些颜色是否可行。判断过程用搜索。搜索的方法是,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 ;
return a > ? : -;
} 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)) < ;
} 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 = ;
for (int i = ; i < polygon_num; i++)
{
char territory_name[];
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 = ;
polygon[i].id = territory_id[name];
while ()
{
int j = polygon[i].point_num;
scanf("%lf", &polygon[i].point[j].x);
if (polygon[i].point[j].x == -)
break;
scanf("%lf", &polygon[i].point[j].y);
polygon[i].point_num++;
}
}
} bool neighbour(Polygon &a, Polygon &b)
{
for (int i = ; i < a.point_num; i++)
{
for (int j = ; j < b.point_num; j++)
{
Line l1 = Line(a.point[i], a.point[(i + ) % a.point_num]);
Line l2 = Line(b.point[j], b.point[(j + ) % b.point_num]);
if (overlap(l1, l2))
return true;
}
}
return false;
} void create_graph()
{
memset(graph, , sizeof(graph));
for (int i = ; i < polygon_num - ; i++)
{
for (int j = i + ; 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 = ; 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 = ; i < color_num; i++)
{
color[u] = i;
if (!ok(u))
continue;
if (dfs(color_num, u + ))
return true;
}
color[u] = -;
return false;
} int main()
{
while (scanf("%d", &polygon_num), polygon_num)
{
input();
create_graph();
int ans = ;
while (ans <= )
{
ans++;
memset(color, -, sizeof(color));
color[] = ;
if (dfs(ans, ))
{
printf("%d\n", ans);
break;
}
}
}
return ;
}

poj2148的更多相关文章

  1. poj分类 很好很有层次感。

    初期: 一.基本算法:      (1)枚举. (poj1753,poj2965)      (2)贪心(poj1328,poj2109,poj2586)      (3)递归和分治法.      ( ...

  2. 【转】POJ题目分类推荐 (很好很有层次感)

    OJ上的一些水题(可用来练手和增加自信) (poj3299,poj2159,poj2739,poj1083,poj2262,poj1503,poj3006,poj2255,poj3094)初期: 一. ...

  3. 【转】ACM训练计划

    [转] POJ推荐50题以及ACM训练方案 -- : 转载自 wade_wang 最终编辑 000lzl POJ 推荐50题 第一类 动态规划(至少6题, 和 必做) 和 (可贪心) (稍难) 第二类 ...

  4. POJ 题目分类(转载)

    Log 2016-3-21 网上找的POJ分类,来源已经不清楚了.百度能百度到一大把.贴一份在博客上,鞭策自己刷题,不能偷懒!! 初期: 一.基本算法: (1)枚举. (poj1753,poj2965 ...

  5. (转)POJ题目分类

    初期:一.基本算法:     (1)枚举. (poj1753,poj2965)     (2)贪心(poj1328,poj2109,poj2586)     (3)递归和分治法.     (4)递推. ...

  6. acm常见算法及例题

    转自:http://blog.csdn.net/hengjie2009/article/details/7540135 acm常见算法及例题  初期:一.基本算法:     (1)枚举. (poj17 ...

  7. poj分类

    初期: 一.基本算法:      (1)枚举. (poj1753,poj2965)      (2)贪心(poj1328,poj2109,poj2586)      (3)递归和分治法.      ( ...

  8. 转载 ACM训练计划

    leetcode代码 利用堆栈:http://oj.leetcode.com/problems/evaluate-reverse-polish-notation/http://oj.leetcode. ...

  9. ACM算法总结及刷题参考

    参考:http://bbs.byr.cn/#!article/ACM_ICPC/11777 OJ上的一些水题(可用来练手和增加自信)(poj3299,poj2159,poj2739,poj1083,p ...

随机推荐

  1. PAT 甲级 1096 Consecutive Factors

    https://pintia.cn/problem-sets/994805342720868352/problems/994805370650738688 Among all the factors ...

  2. CentOS 简单学习 firewalld的使用

    1. centos7 开始 使用firewalld 代替了 iptables 命令工具为 firewall-cmd 帮助信息非常长,简单放到文末 2. 简单使用 首先开启 httpd 一般都自带安装了 ...

  3. Linux系统编程手册-源码的使用

    转自:http://www.cnblogs.com/pluse/p/6296992.html 第三章后续部分重点介绍了后面章节所要使用的头文件及其实现,主要如下: ename.c.inc error_ ...

  4. Rabbitmq基本原理(转)

    https://www.cnblogs.com/jun-ma/p/4840869.html

  5. linq partition by

    static void Main(string[] args) { var beatles = (new[] { new { id=1 , inst = "guitar" , na ...

  6. 【BZOJ1093】[ZJOI2007]最大半联通子图(Tarjan,动态规划)

    [BZOJ1093][ZJOI2007]最大半联通子图(Tarjan,动态规划) 题面 BZOJ 洛谷 洛谷的讨论里面有一个好看得多的题面 题解 显然强连通分量对于题目是没有任何影响的,直接缩点就好了 ...

  7. BZOJ 2561 最小生成树 | 网络流 最小割

    链接 BZOJ 2561 题解 用Kruskal算法的思路来考虑,边(u, v, L)可能出现在最小生成树上,就是说对于所有边权小于L的边,u和v不能连通,即求最小割: 对于最大生成树的情况也一样.容 ...

  8. 【转】spi测试自发自收(中断通信方式)

    1.初始化spi时钟 void spiRccinit(void) { RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); RCC_APB2Peri ...

  9. jenkins构建docker镜像上传到harbor并发布到kubernetes

    很早之前写过一篇jenkins集成docker的文章,使用的是CloudBees Docker Build and Publish plugin插件.这篇文章是直接使用shell脚本做的,主要是这次有 ...

  10. Django通过中间件实现登录验证demo

    前提:中间件版的登录验证需要依靠session,所以数据库中要有django_session表. from django.conf.urls import url from django.contri ...