例题6-22 战场 UVa11853

1.题目描述:点击打开链接

2.解题思路:本题初看起来比较麻烦,不妨简化一下:先判断是否有解,再考虑如何求出解。根据题意描述,相当于在一个正方形中有若干个圆形障碍物,问是否能从左边界走到右边界。判断是否有解需要一点创造性的思维:不妨把正方形当做一个湖,所有的圆形都是垫脚石,假设我们可以从上边界“踩着”垫脚石成功走到下边界,说明左右边界是不连通的;否则就是连通的。想到了这里,便不难用dfs或bfs来判断是否有解了:每次都从和上边界相交的圆开始进行dfs,如果遇到某个圆和下边界也相交,那么无解。

那么如何寻找解呢,根据题意需要找到最靠近北边的。这样的话,只需要找到所有与左边界相交的圆中最靠南边的交点即可,同理可以找到右边界的解。

本题在数据处理上有一个小技巧:把圆形设计成一个结构体,维护圆心坐标和半径,同时用read成员函数读入数据,比用scanf函数方便了很多。

3.代码:

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<algorithm>
#include<string>
#include<sstream>
#include<set>
#include<vector>
#include<stack>
#include<map>
#include<queue>
#include<deque>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<ctime>
#include<functional>
using namespace std;

#define N 1000+10
struct Circle
{
	int x, y, r;
	void read()
	{
		scanf("%d%d%d", &x, &y, &r);
	}
}c[N];
double ans1, ans2;
int n, vis[N];

bool can(Circle a, Circle b)//判断两个圆是否相交或相切
{
	int dx = a.x - b.x;
	int dy = a.y - b.y;
	return dx*dx + dy*dy - (a.r + b.r)*(a.r + b.r) <= 0;
}
bool dfs(int u)
{
	vis[u] = 1;
	if (c[u].y - c[u].r <= 0)return false;//圆和下边界有交点,说明不存在解,直接退出
	if (c[u].x - c[u].r <= 0)ans1 = min(ans1, c[u].y - sqrt(c[u].r*c[u].r - c[u].x*c[u].x));//与左边界有交点,取纵坐标的较小者
	if (1000 - c[u].x - c[u].r <= 0)ans2 = min(ans2, c[u].y - sqrt(c[u].r*c[u].r - (1000 - c[u].x)*(1000 - c[u].x)));//与右边界有交点,取纵坐标较小者
	for (int i = 0; i < n; i++)
	if (!vis[i])
	{
		if (can(c[u], c[i]))//路径可以继续扩展
		if (!dfs(i))return false;
	}
	return true;
}
void solve()
{
	ans1 = ans2 = 1000;
	for (int i = 0; i < n; i++)
	if (!vis[i] && c[i].y + c[i].r>=1000)//从与上边界有交点的圆出发
	{
		if (!dfs(i))//不存在解,如果存在解那么每次dfs后都会更新解
		{
			puts("IMPOSSIBLE");
			return;
		}
	}
	printf("0.00 %.2lf 1000.00 %.2lf\n", ans1, ans2);
}
int main()
{
	//freopen("t.txt", "r", stdin);
	while (~scanf("%d", &n))
	{
		memset(vis, 0, sizeof(vis));
		for (int i = 0; i < n; i++)
			c[i].read();//利用成员函数方便读入数据
		solve();
	}
	return 0;
}
时间: 2024-08-05 15:24:31

例题6-22 战场 UVa11853的相关文章

例题 2-1 aabb 2-2 3n+1问题

例题2-1  aabb 输出所有形如aabb的四位完全平方数(即前两位数字相等,后两位数字也相等) #include <stdio.h> #include <stdlib.h> #include <math.h> int main(int argc, char *argv[]) { int i, j, n; double m; for(i = 1; i <= 9; i++) for(j = 0; j <= 9; j++) { n = i*1100 + j*1

关于一道数据库例题的解析。为什么σ age&gt;22 (πS_ID,SCORE (SC) ) 选项是错的?

本人大二学子.近段时间在做数据库复习题的时候遇到一道题,如下. 有关系SC(S_ID,C_ID,AGE,SCORE),查找年龄大于22岁的学生的学号和分数,正确的关系代数表达式是( ) . ⅰ. πS_ID,SCORE (σ age>22 (SC) ) ⅱ. σ age>22 (πS_ID,SCORE (SC) ) ⅲ. πS_ID,SCORE (σage>22 (πS_ID,SCORE,AGE (SC) ) ) 答案是 i和iii,当时我自己做的结果是三个都正确.看了答案后,总是觉得

9.22下午 JS\document例题讲解

作业一:两个列表之间数据从一个列表移动到另一个列表 <div style="width:600px; height:500px; margin-top:20px"> <div style="width:200px; height:300px; float:left"> <select id="list1" size="10" style="width:200px; height:300p

黑书例题 Fight Club 区间DP

题目可以在bnuoj.soj等OJ上找到. 题意: 不超过40个人站成一圈,只能和两边的人对战.给出任意两人对战的输赢,对于每一个人,输出是否可能是最后的胜者. 分析: 首先序列扩展成2倍,破环成链. dp[i][j]表示i和j能够相遇对打,那么dp[i][i+n]为真代表可以成为最后胜者. 枚举中间的k,若i和j都能和k相遇,且i和j至少一人能打赢k,那么i和j可以相遇. 复杂度o(n^3) 1 #include<cstdio> 2 #include<cstring> 3 usi

linux脚本进阶例题解析

例题一:编写脚本/root/bin/createuser.sh,实现如下功能: 使用一个用户名做为参数,如果指定参数的用户存在,就显示其存在,否则添加之:并生成8位随机口令并存在一个文件中,初步提示改口令,显示添加的用户的id号等信息 #!/bin/bash # ------------------------------------------ # Filename: useradd.sh  # Revision: null # Date: 2017-09-11 21:47:22 # Auth

【强连通分量】tarjan算法及kosaraju算法+例题

阅读前请确保自己知道强连通分量是什么,本文不做赘述. Tarjan算法 一.算法简介 Tarjan算法是一种由Robert Tarjan提出的求有向图强连通分量的时间复杂度为O(n)的算法. 首先我们要知道两个概念:时间戳(DFN),节点能追溯到的最早的栈中节点的时间戳(LOW).顾名思义,DFN就是在搜索中某一节点被遍历到的次序号(dfs_num),LOW就是某一节点在栈中能追溯到的最早的父亲节点的搜索次序号. Tarjan算法是基于深度优先搜索的算法.在搜索过程中把没有Tarjan过的点入栈

第10章例题(紫书)

21/21 题目都很基础,有很多题书上讲得比较详细,然后隔得时间有点久,所以具体什么trick都忘了,思路也懒得去回忆,所以将就着放上来了.... 例题10–1 Uva 11582 题意:输入a, b, n让你计算F[a^b]%n;其中这个F[i]是斐波那契数: 题解: 这题是快速幂+找循环节,用什么方法找循环节呢?因为第一个数是0和1,然后当再出现0和1的时候就是出现循环节的时候,然后假如找到了循环节T,然后就有F[n] = F[n % T],预处理找循环节,O(一百万左右),快速幂logn

[入门向选讲] 插头DP:从零概念到入门 (例题:HDU1693 COGS1283 BZOJ2310 BZOJ2331)

转载请注明原文地址:http://www.cnblogs.com/LadyLex/p/7326874.html 最近搞了一下插头DP的基础知识……这真的是一种很锻炼人的题型…… 每一道题的状态都不一样,并且有不少的分类讨论,让插头DP十分锻炼思维的全面性和严谨性. 下面我们一起来学习插头DP的内容吧! 插头DP主要用来处理一系列基于连通性状态压缩的动态规划问题,处理的具体问题有很多种,并且一般数据规模较小. 由于棋盘有很特殊的结构,使得它可以与“连通性”有很强的联系,因此插头DP最常见的应用要数

[提升性选讲] 树形DP进阶:一类非线性的树形DP问题(例题 BZOJ4403 BZOJ3167)

转载请注明原文地址:http://www.cnblogs.com/LadyLex/p/7337179.html 树形DP是一种在树上进行的DP相对比较难的DP题型.由于状态的定义多种多样,因此解法也五花八门,经常成为高水平考试的考点之一. 在树形DP的问题中,有这样一类问题:其数据范围相对较小,并且状态转移一般与两两节点之间的某些关系有关. 今天,我们就来研究一下这类型的问题,并且总结一种(相对套路的)解决大多数类型题的思路. 首先,我们用一道相对简单的例题来初步了解这个类型题的大致思路,以及一