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 ;
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的更多相关文章
- poj分类 很好很有层次感。
初期: 一.基本算法: (1)枚举. (poj1753,poj2965) (2)贪心(poj1328,poj2109,poj2586) (3)递归和分治法. ( ...
- 【转】POJ题目分类推荐 (很好很有层次感)
OJ上的一些水题(可用来练手和增加自信) (poj3299,poj2159,poj2739,poj1083,poj2262,poj1503,poj3006,poj2255,poj3094)初期: 一. ...
- 【转】ACM训练计划
[转] POJ推荐50题以及ACM训练方案 -- : 转载自 wade_wang 最终编辑 000lzl POJ 推荐50题 第一类 动态规划(至少6题, 和 必做) 和 (可贪心) (稍难) 第二类 ...
- POJ 题目分类(转载)
Log 2016-3-21 网上找的POJ分类,来源已经不清楚了.百度能百度到一大把.贴一份在博客上,鞭策自己刷题,不能偷懒!! 初期: 一.基本算法: (1)枚举. (poj1753,poj2965 ...
- (转)POJ题目分类
初期:一.基本算法: (1)枚举. (poj1753,poj2965) (2)贪心(poj1328,poj2109,poj2586) (3)递归和分治法. (4)递推. ...
- acm常见算法及例题
转自:http://blog.csdn.net/hengjie2009/article/details/7540135 acm常见算法及例题 初期:一.基本算法: (1)枚举. (poj17 ...
- poj分类
初期: 一.基本算法: (1)枚举. (poj1753,poj2965) (2)贪心(poj1328,poj2109,poj2586) (3)递归和分治法. ( ...
- 转载 ACM训练计划
leetcode代码 利用堆栈:http://oj.leetcode.com/problems/evaluate-reverse-polish-notation/http://oj.leetcode. ...
- ACM算法总结及刷题参考
参考:http://bbs.byr.cn/#!article/ACM_ICPC/11777 OJ上的一些水题(可用来练手和增加自信)(poj3299,poj2159,poj2739,poj1083,p ...
随机推荐
- CMS垃圾收集器与G1收集器
1.CMS收集器 CMS收集器是一种以获取最短回收停顿时间为目标的收集器.基于“标记-清除”算法实现,它的运作过程如下: 1)初始标记 2)并发标记 3)重新标记 4)并发清除 初始标记.从新标记这两 ...
- Windows XP 安装使用的序列号
SP3 X86 MRX3F-47B9T-2487J-KWKMF-RPWBY SP2 X64 B66VY-4D94T-TPPD4-43F72-8X4FY 注意 X64 没有SP3的包 用的是跟 2003 ...
- 解决Ubuntu14.04下sublime无法输入中文
原帖地址: (简书作者) http://www.jianshu.com/p/bf05fb3a4709 前言 sublime很好用,但是ubuntu14.04 下不能输入中文,这是一个很大的问题.不知道 ...
- DELPHI动态创建窗体
//第一种方式 procedure TForm1.btn1Click(Sender: TObject); begin With TForm2.Create(Application) do Try Sh ...
- hdwiki5.1 词条参考资料都是相同的问题解决
HDWiki 5.1版本存在的BUG,当一个词条添加参考资料后,所有词条均显示以此相同的参考资料:而且参考资料不能修改和删除! 解决方法如下: 找到后台文件:\model\reference.clas ...
- STEM 是个怎样高大上的东西?
近几年来,STEM 教育概念传入中国,并且越来越多地成为家长及教育机构关注的焦点. STEM教育概念同时成为了各大小教育机构及公司宣传造势的赚钱工具,可家长.学生.老师们真的理解究竟何为 STEM/S ...
- 【BZOJ2084】[Poi2010]Antisymmetry(manarcher)
[BZOJ2084][Poi2010]Antisymmetry(manarcher) 题面 BZOJ 洛谷 题解 一眼马拉车吧...明显就是在回文串的基础上随便改了改. 似乎还可以魔改回文树,然而我这 ...
- 【转】PCB中3D相关功能详解
如果PCB Layout工程师能够在设计过程中,使用设计工具直观地看到自己设计板子的实际情况,将能够有效的帮助他们的工作.尤其现在PCB板的设计越来越复杂,密度越来越高,如果能够洞察多层板内部则可以帮 ...
- P3232 [HNOI2013]游走 解题报告
P3232 [HNOI2013]游走 题目描述 一个无向连通图,顶点从\(1\)编号到\(N\),边从\(1\)编号到\(M\). 小Z在该图上进行随机游走,初始时小Z在1号顶点,每一步小Z以相等的概 ...
- 自动化部署之搭建yum仓
一.导言 YUM主要用于自动安装.升级rpm软件包,它能自动查找并解决rpm包之间的依赖关系.要成功的使用YUM工具安装更新软件或系统,就需要有一个包含各种rpm软件包的repository(软件仓库 ...