UVa 1303 - Wall

题目:有很多点,修一座最短的围墙把素有点围起来,使得所有点到墙的距离不小于l。

分析:计算几何,凸包。

如果,没有距离l的限制,则答案就是凸包的周长了;有了距离限制其实是增加了2*π*l;

证明:如上图,在凸包外做对应边的矩形;

多边形内角和 = 180*(n-2);

外角和 = 360*n - 内角和 = 180*n+360;

所有直角和为2*90*n;

所以,所有扇形的内角和为360;即围栏比凸多边形周长多2*π*l。

说明:坐标比较a3.x < b.x 写成 a.x < b.y 查了好久才发现,o(╯□╰)o

#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cmath>

using namespace std;

typedef struct pnode
{
	int  x,y;
	double d;
}point;
point P[1005];

//叉乘
int crossProduct(point a, point b, point c)
{
	return (b.x-a.x)*(c.y-a.y)-(c.x-a.x)*(b.y-a.y);
}

//两点间距离
double dist(point a, point b)
{
	return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)+0.0);
}

//坐标比较
int cmp1(point a, point b)
{
	if (a.x == b.x) return a.y < b.y;
	return a.x < b.x;
}

//斜率比较
int cmp2(point a, point b)
{
	int cp = crossProduct(P[0], a, b);
	if (!cp) return a.d < b.d;
	return cp > 0;
}

//凸包
double Graham(int n)
{
	sort(P+0, P+n, cmp1);
	for (int i = 1 ; i < n ; ++ i)
		P[i].d = dist(P[0], P[i]);
	sort(P+1, P+n, cmp2);

	int top = 1;
	for (int i = 2 ; i < n ; ++ i) {
		while (top > 0 && crossProduct( P[top-1], P[top], P[i] ) < 0) -- top;
		P[++ top] = P[i];
	}
	P[++ top] = P[0];

	double L = 0.0;
	for ( int i = 0 ; i < top ; ++ i )
		L += dist(P[i], P[i+1]);
	return L;
}

int main()
{
	int t,n,l;
	while (~scanf("%d",&t))
	while (t --) {
		scanf("%d%d",&n,&l);
		for (int i = 0 ; i < n ; ++ i)
			scanf("%d%d",&P[i].x,&P[i].y);

		printf("%.0lf\n",Graham(n)+acos(-1.0)*2*l);
		if (t) printf("\n");
	}
	return 0;
}
时间: 2025-01-15 06:26:35

UVa 1303 - Wall的相关文章

【暑假】[深入动态规划]UVa 10618 Fixing the Great Wall

UVa 10618 Fixing the Great Wall 题目:  http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=36139 思路:   数轴上有n个点需要修复,每个点有信息c,x,d 表示位于x且在t时修缮的费用是c+d*t,找一个修缮序列使n个点能全部修缮且有费用最小. 可以发现:在任意时刻,修缮完的点都是连续的,因为修缮不需要时间,将一些点“顺手”修缮了肯定不差. d[i][j][k],表示已经将i-j个点修缮

UVA 1045 - The Great Wall Game(二分图完美匹配)

UVA 1045 - The Great Wall Game 题目链接 题意:给定一个n*n的棋盘,有n个棋子在上面,现在要移动棋子,每一步代价是1,现在要把棋子移动到一行,一列,或者在主副对角线上,问最小代价 思路:二分图完美匹配,枚举每种情况,建边,边权为曼哈顿距离,然后km算法做完美匹配算出值即可,由于要求最小值所以边权传负数,这样做出来的值的负就是答案 代码: #include <cstdio> #include <cstring> #include <cmath&g

Fixing the Great Wall UVA - 1336(区间dp)

Fixing the Great Wall UVA - 1336 题意:修长城,初始位置为fp,n个点要修,初始每个点修缮费用为ci,单位时间增加费用di,问最少费用. 区间dp 和送外卖那个差不多~ 有一个细节,输入不加!=EOF的话会超时(虽然题目说了以00结束) 1 #include <cstdio> 2 #include <bits/stdc++.h> 3 using namespace std; 4 const int maxn=1005; 5 struct node 6

【UVA】11040 - Add bricks in the wall(找规律)

一道找规律的题,可以看出,大的三角形可以划分成好多个三层的三角形: [x] [a][x-a] [y] [    ][z] 这里面xyz都已知,所以可以求出a = (x + y - z ) /2 14043615 11040 Add bricks in the wall Accepted C++ 0.019 2014-08-15 06:02:50 #include<cstdio> #include<cstring> #include<iostream> #include&

UVA 11040 Add bricks in the wall

https://vjudge.net/problem/UVA-11040 找规律 #include<cstdio> using namespace std; int a[10][10]; int main() { int T,d; scanf("%d",&T); while(T--) { for(int i=1;i<=5;i++) for(int j=1;j<=i;j++) scanf("%d",&a[i*2-1][j*2-1

UVa 11040 Add bricks in the wall (水题递推)

题意:给定一个金字塔,除了最后一行,每个数都等于支撑它的两个数的和,现在给奇数行的左数奇数位置,求整个金字塔. 析:很容易看出来,从下往上奇数行等于 a[i][j] = (a[i-2][j-1] - a[i][j-1] - a[i][j+1]) / 2;然后偶数行就推出来了. 代码如下: #pragma comment(linker, "/STACK:1024000000,1024000000") #include <cstdio> #include <string&

UVa 1336 Fixing the Great Wall (区间DP)

题意:给定 n 个结点,表示要修复的点,然后机器人每秒以 v 的速度移动,初始位置在 x,然后修复结点时不花费时间,但是如果有的结点暂时没修复, 那么每秒它的费用都会增加 d,修复要花费 c,坐标是 pos,问你最少花费是多少. 析:dp[i][j][k] 表示已经修复了 i-j 区间,并且当前在 k,那么两种方案,向左移动,或者向右移动,最后输出就好了. 代码如下: #pragma comment(linker, "/STACK:1024000000,1024000000") #in

UVA, 900 Brick Wall Patterns

题意:给你长度为2,宽度为1的砖,给你一定长度,求可以摆的砖的方式,看图更容易理解↓ 思路:递推 1:1 2:1+1=2 3:1+2=3 4:2+3=5 5:3+5=8 …… 满足规律:m[x]=m[x-1]+m[x-2] 代码: 1 #include <iostream> 2 #include <cstdio> 3 using namespace std; 4 int n; 5 #define MAXN 51 6 long long m[MAXN]; 7 bool datecin

UVa 11040 (水题) Add bricks in the wall

题意: 45块石头如图排列,每块石头上的数等于下面支撑它的两数之和,求其余未表示的数. 分析: 首先来计算最下面一行的数,A71 = A81 + A82 = A91 + 2A92 + A93,变形得到A92 = (A71 - A91 - A93) / 2. 以此类推,就能得到最下面一整行的数.有了这个“地基”以后,所有的数就都能算出来了. 1 #include <cstdio> 2 3 int a[10][10]; 4 5 int main() 6 { 7 //freopen("in