LightOJ 1313 - Protect the Mines(凸包)
| Time Limit: 2 second(s) | Memory Limit: 32 MB |
You are a rich man, and recently you bought a place which contains some mines of rare metals like gold, platinum etc. As the metals are rare, their cost is also so high. So, you need to protect them from thieves. But things are not as easy as it looks.
So, you called a bunch of engineers to make some wired fences around the mines. As they were just engineers (not problem solvers!), they drilled some holes in random places. The idea was to put some pillars on the drilled holes and after that some wires should be set in the pillars, and finally electrifying the wires would be the completion. And of course, each mine should be surrounded by a fence. Wires should be placed between two pillars, in straight lines. The engineers drilled the holes in positions such that some of the mines might not be covered by any fences.
However, your plan is that, you can put some guards in mines that are not surrounded by any fence. To guard a single mine, it would cost G dollars, and a pillar cost is P dollars. As you are a rich man, the costs of wires are too small that they can be ignored. So, you want to put guards in some mines and surround some other mines by fences, but you want to find the optimal cost to protect all the mines. The fences may or may not be convex.
In bird's eye view, we can get the following figure (fig 1) for sample 1. There are seven pre-drilled holes (marked as circles), and six mine positions (marked as squares). The straight lines show the wires and the closed regions form the fences. The figure shows one of the optimal solutions.
Fig 1
So, you have to find the minimum cost for executing your plan.
Input
Input starts with an integer T (≤ 100), denoting the number of test cases.
Each case starts with a line containing four integers N (3 ≤ N ≤ 100), M (1 ≤ M ≤ 100), G (1000 ≤ G ≤ 2000) and P (100 ≤ P ≤ 200), N denotes the number of pre-drilled holes, and M denotes the number of mines. This line is followed by N lines that describe the positions of the holes, and then by M lines that describe the positions of the mines. All positions are given as pairs of integers x y on one line (0 ≤ x, y ≤ 1000). You can assume that no two positions (of holes and mines) coincide and that no three positions are collinear.
Output
For each case, print the case number and the minimum cost to protect all the mines.
Sample Input |
Output for Sample Input |
|
2 7 6 1000 100 0 0 20 0 1 10 39 10 1 20 39 20 20 30 3 9 37 9 3 21 37 21 18 24 50 24 4 3 1500 100 0 0 0 10 10 0 10 10 5 4 4 1 8 6 |
Case 1: 1600 Case 2: 300 |
首先根据题目意思,
一个mine如果可以被holes覆盖的话,肯定在一个三角形里面,因为G比P至少大10倍,所以最佳策略就是把可以覆盖的全部覆盖掉,其余的加士兵上去。
首先求一下凸包,把凸包内部的所有mines都找出来。
然后搞floyed, 就是看最少几步可以形成环,把所有都包括进来,
debug了好久,太坑了,以后写几何要慎重了。
/* ***********************************************
Author :kuangbin
Created Time :2014/4/22 19:32:10
File Name :E:\2014ACM\专题学习\计算几何\凸包\LightOJ1313.cpp
************************************************ */ #include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <string>
#include <math.h>
#include <stdlib.h>
#include <time.h>
using namespace std; // 计算几何int 版,注意如果超int,相应的要改为long long
const int maxp = ;
struct Point
{
int x,y;
Point(){}
Point(int _x,int _y)
{
x = _x; y = _y;
}
void input()
{
scanf("%d%d",&x,&y);
}
bool operator == (Point b)const
{
return x == b.x && y == b.y;
}
bool operator < (Point b)const
{
return x == b.x ? y < b.y : x < b.x;
}
Point operator - (const Point &b)const
{
return Point(x-b.x,y-b.y);
}
int operator ^ (const Point &b)const
{
return x*b.y - y*b.x;
}
int operator *(const Point &b)const
{
return x*b.x + y*b.y;
}
double len2()
{
return x*x + y*y;
}
};
struct Line
{
Point s,e;
Line(){}
Line(Point _s,Point _e)
{
s = _s;
e = _e;
}
//点和直线关系
//1 在左侧
//2 在右侧
//3 在直线上
int relation(Point p)
{
int c = (p-s)^(e-s);
if(c < )return ;
else if(c > )return ;
else return ;
}
bool pointonseg(Point p)
{
return ((p-s)^(e-s)) == && ((p-s)*(p-e)) <= ;
}
};
struct polygon
{
int n;
Point p[maxp];
void input(int _n)
{
n = _n;
for(int i = ;i < n;i++)
p[i].input();
}
struct cmp
{
Point p;
cmp(const Point &p0){p = p0;}
bool operator()(const Point &aa,const Point &bb)
{
Point a = aa, b = bb;
int d = (a-p)^(b-p);
if(d == )
return (a-p).len2() < (b-p).len2();
return d > ;
}
};
void norm()
{
Point mi = p[];
for(int i = ;i < n;i++)
mi = min(mi,p[i]);
sort(p,p+n,cmp(mi));
}
void getconvex(polygon &convex)
{
sort(p,p+n);
convex.n = n;
for(int i = ;i < min(n,);i++)
{
convex.p[i] = p[i];
}
if(n <= )return;
int &top = convex.n;
top = ;
for(int i = ;i < n;i++)
{
while(top && ((convex.p[top]-p[i])^(convex.p[top-]-p[i]))<=)
top--;
convex.p[++top] = p[i];
}
int temp = top;
convex.p[++top] = p[n-];
for(int i = n-;i >= ;i--)
{
while(top != temp && ((convex.p[top]-p[i])^(convex.p[top-]-p[i]))<=)
top--;
convex.p[++top] = p[i];
}
convex.norm();
}
//判断点和任意多边形的关系
//3 点上
//2 边上
//1 内部
//0 外部
int relation(Point q)
{
for(int i = ;i < n;i++)
{
if(p[i] == q)return ;
}
for(int i = ;i < n;i++)
{
if(Line(p[i],p[(i+)%n]).pointonseg(q))return ;
}
int cnt = ;
for(int i = ;i < n;i++)
{
int j = (i+)%n;
int k = ((q-p[j])^(p[i]-p[j]));
int u = (p[i].y-q.y);
int v = (p[j].y-q.y);
if(k > && u < && v >= )cnt++;
if(k < && v < && u >= )cnt--;
}
return cnt != ;
}
};
Point mines[maxp];
Point mines2[maxp];
int cnt;
polygon A,B;
bool check(Line v)
{
for(int i = ;i < cnt;i++)
if(v.relation(mines2[i]) != )
return false;
return true;
}
int a[][];
int b[][];
int c[][];
int solve(polygon A)
{
int n = A.n;
memset(a,,sizeof(a));
for(int i = ;i < n;i++)
for(int j = ;j < n;j++)
if(i != j && check(Line(A.p[i],A.p[j])))
a[i][j] = ;
for(int i = ;i < n;i++)
for(int j = ;j < n;j++)
b[i][j] = a[i][j];
for(int s = ;s <= n;s++)
{
for(int i = ;i < n;i++)
for(int j = ;j < n;j++)
c[i][j] = b[i][j];
memset(b,,sizeof(b));
for(int i = ;i < n;i++)
for(int j = ;j < n;j++)
for(int k = ; k < n;k++)
if(c[i][k] && a[k][j])
b[i][j] = ;
for(int i = ;i < n;i++)
if(b[i][i])
return s;
}
return -;
} int main()
{
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
int T;
int n,m,g,p;
int iCase = ;
scanf("%d",&T);
while(T--)
{
iCase++;
scanf("%d%d%d%d",&n,&m,&g,&p);
A.input(n);
for(int i = ;i < m;i++)
mines[i].input();
A.getconvex(B);
cnt = ;
//找出在凸包内的
for(int i = ;i < m;i++)
if(B.relation(mines[i]) == )
mines2[cnt++] = mines[i];
int ans1 = (m-cnt)*g;
int tmp = ;
if(cnt)tmp = solve(A);
printf("Case %d: %d\n",iCase,ans1 + tmp*p);
}
return ;
}
LightOJ 1313 - Protect the Mines(凸包)的更多相关文章
- LightOJ 1203--Guarding Bananas(二维凸包+内角计算)
1203 - Guarding Bananas PDF (English) Statistics Forum Time Limit: 3 second(s) Memory Limit: 32 M ...
- LightOJ 1239 - Convex Fence 凸包周长
LINK 题意:类似POJ的宫殿围墙那道,只不过这道题数据稍微强了一点,有共线的情况 思路:求凸包周长加一个圆周长 /** @Date : 2017-07-20 15:46:44 * @FileNam ...
- LightOJ 1203 Guarding Bananas (凸包最小顶角)
题目链接:LightOJ 1203 Problem Description Once there was a lazy monkey in a forest. But he loved banana ...
- UVa 109 - SCUD Busters(凸包计算)
题目来源:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=3&pa ...
- LightOj1203 - Guarding Bananas(凸包求多边形中的最小角)
题目链接:http://lightoj.com/volume_showproblem.php?problem=1203 题意:给你一个点集,求凸包中最小的角:模板题,但是刚开始的时候模板带错了,错的我 ...
- HDU 4946 Area of Mushroom 凸包
链接:pid=4946">http://acm.hdu.edu.cn/showproblem.php?pid=4946 题意:有n个人.在位置(xi,yi),速度是vi,假设对于某个点 ...
- POJ 1873 The Fortified Forest [凸包 枚举]
The Fortified Forest Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 6400 Accepted: 1 ...
- poj 1873 凸包+枚举
The Fortified Forest Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 6198 Accepted: 1 ...
- poj1873(枚举+凸包)
The Fortified Forest Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 7291 Accepted: 2 ...
随机推荐
- OS实验一实验报告
实验一.命令解释程序的编写实验 专业:商业软件工程 姓名:王泽锴 学号:201406114113 一.实验目的 (1)掌握命令解释程序的原理: (2)*掌握简单的DOS调用方法: (3)掌握C语 ...
- *** glibc detected *** malloc(): memory corruption 分类: C/C++ Linux 2015-05-14 09:22 37人阅读 评论(0) 收藏
*** glibc detected *** malloc(): memory corruption: 0x09eab988 *** 发现是由于memset越界写引起的. 在Linux Server上 ...
- Spring源码学习之:ClassLoader学习(2)
转载:http://longdick.iteye.com/blog/332580 大家都知道一个java应用项目可以打包成一个jar,当然你必须指定一个拥有main函数的main class作为你这个 ...
- 打印心形---print 的基础使用
#!/bin/usr/env python#coding=utf-8'''用学习到的print语句,完成如下图形的打印工作打印心形'''print " *** *** "print ...
- Apache Shiro简介
作者:var dump链接:https://zhuanlan.zhihu.com/p/23300328最近要做一个基于Java C/S架构的项目,主要涉及权限管理这方面的东西.了解到Apache Sh ...
- Linux安装gcc编译器详解
本人使用的是CentOS 6.5 64位系统,由于在安装系统的时候并没有勾选安装gcc编译器,因此需要自行安装gcc编译器. 使用yum安装gcc 对于配备了yum的Linux发行版而言,安装gcc编 ...
- knockout 学习实例7 foreach
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...
- UML精粹1 - 简介
Martin的主页 http://martinfowler.com/. Pavel Hruby开发的visio模板,可以用来画UML图: http://phruby.com 简介 统一建模语言UML是 ...
- 把自己主要在做的几个工程都传到了GitHub上
GitHub链接 https://github.com/MichaelSuen-thePointer 里面有4个项目,一个是我的C大程大作业,一个3600+行的字典程序,已经弃坑不再更新 还有一个叫w ...
- throw和throws的区别
1. 作用不同: throw用于在程序中抛出异常;throws用于声明在该方法内抛出异常, 2. 使用位置不同:throw位于方法体内部,可以作为单独语句使用,throws必须跟着 ...