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 ...
随机推荐
- PAT乙级(Basic Level)练习题-NowCoder数列总结
题目描述 NowCoder最近在研究一个数列: F(0) = 7 F(1) = 11 F(n) = F(n-1) + F(n-2) (n≥2) 他称之为NowCoder数列.请你帮忙确认一下数列中第n ...
- Oracle 数据库执行 操作系统的命令
1 Linux环境下面的处理 在sqlplus 里面 添加一个 ! 就可以执行 但是 因为Oracle 必须为非root用户 所以很多命令可能无法执行: 2. Windows 环境执行命令的方式 是在 ...
- array_column 函数, 以及在PHP5.5之下的替代方法
array_column 函数, 是能够根据多维数组中共有的一个键值来提取多维数组中属于这个键的值 例如下面的数组: $test = array( 0 => array( 'id' => ...
- Spring注入的不同方式
1.直接创建一个Bean <bean id="dboperate" class="study.spring2.Test"></bean> ...
- java 重载 : 1.参数个数不同,2.参数类型不同
参数个数相同时,参数类型需要不同,即使是不同变量名也不行.和是和变量的个数或者是变量的类型有关系 如果相同的话是覆盖 会报错 重载(overloading) 是在一个类里面,方法名字相同,而参数不同 ...
- 如何把EntityList转换成DataSet
public static DataSet ToDataSet<TSource>(this IList<TSource> list) { Type elementType = ...
- 使用doxygen静态分析开源代码
doxygen是一款生成开源代码说明文件的工具,因为不需要编译源码,用作代码的分析也十分方便. 一.安装 sudo apt-get install graphviz sudo apt-get inst ...
- windows10中远程登录ubuntu16.04的桌面
1. 安装xrdp sudo apt-get install xrdp 2. 安装vnc4server sudo apt-get install vnc4server tightvncserver ...
- 【题解】 [SDOI2009] Elaxia的路线(最短路+拓扑排序)
懒得复制,戳我戳我 Solution: 题目大概意思就是找两条最短路后,找出最长公共部分 我们就只用以四个点为源点开始走\(SPFA\),然后我们就只用遍历每条边然后建立一个新的拓扑图,然后随便搞一下 ...
- python之旅:异常处理
一 什么是异常 异常就是程序运行时发生错误的信号(在程序出现错误时,则会产生一个异常,若程序没有处理它,则会抛出该异常,程序的运行也随之终止),在python中,错误触发的异常如下 一个异常分为三部分 ...