黑马程序员技术交流社区
标题: 算法难题 [打印本页]
作者: 柏占肖 时间: 2012-10-4 03:21
标题: 算法难题
圆面覆盖问题
问题背景
在平面上有一个长为L,宽为W的长方形,左下角坐标为(0,0),右上角坐标为(L,W)。给定一些圆,第i个圆的圆心坐标为(xi,yi),半径为Ri。
你的任务是求最小的正实数k,使得把每个圆的半径变为原来的k倍后(即:第i个圆半径变为kRi,圆心位置不变),长方形将被这些圆完全覆盖。换句话说,长方形内部或边界上的任意点均至少在一个圆的内部或边界上。
输入格式
输入第一行包含三个整数n, L, W(1<=n<=50,1<=L,W<=1000),即圆的个数、长方形的长和宽。
以下n行,每行三个不超过1000的正整数xi, yi和Ri。
输出格式
仅一行,包含一个实数k,保留小数点后三位。
样例输入
1 2 2
1 1 1
样例输出
1.414
感觉这个问题还是很有挑战性的,我也不知道能不能做出来,只能说试试吧,喜欢搞算法的都来试试吧,大家看到了就顶一下吧,在有人贴出答案之前,我不想它沉了,如果有人做出来了,我想请求版主给个2分的技术分,毕竟这个题难度不小呢,做出来的请把注释写详细点,便于大家学习,呵呵……睡觉了
作者: 柏占肖 时间: 2012-10-4 11:03
顶一下
作者: 王宝龙 时间: 2012-10-4 11:09
瞧瞧~~~~~~~~~~~~~~~~
作者: 夏天 时间: 2012-10-4 12:01
啦啦啦,马上升级 金牌黑马~~
作者: 柏占肖 时间: 2012-10-4 13:09
顶起
作者: 李志群 时间: 2012-10-4 18:41
这个百度一搜索 一大片 好像百度之星里面什么试题吧 这个我以前看过 没看明白 0 0!!!!
作者: 杨华东 时间: 2012-10-4 18:52
顶一下
作者: 柏占肖 时间: 2012-10-4 20:44
李志群 发表于 2012-10-4 18:41 
这个百度一搜索 一大片 好像百度之星里面什么试题吧 这个我以前看过 没看明白 0 0!!!! ...
是一道百度之星里面的压轴题呢,40分,等我做出来了再去搜下别人的答案 呵呵
作者: 寇龙飞 时间: 2012-10-5 04:03
mark下,有点困,明天把后续代码搞定。
作者: 王宝龙 时间: 2012-10-5 11:40
本帖最后由 王宝龙 于 2012-10-5 17:09 编辑
代码一枚!!!!问题太多 收回了!!{:soso_e127:}
作者: 柏占肖 时间: 2012-10-5 19:57
顶一下
作者: 柏占肖 时间: 2012-10-6 13:05
顶一下,亲们要给力啊
作者: 柏占肖 时间: 2012-10-8 22:17
顶
作者: 寇龙飞 时间: 2012-10-9 00:04
本帖最后由 寇龙飞 于 2012-10-10 20:26 编辑
- package com.itheima.bixiangdong;
- public class CircleCover {
- /*圆面覆盖问题
- 问题背景
- 在平面上有一个长为L,宽为W的长方形,左下角坐标为(0,0),右上角坐标为(L,W)。给定一些圆,第i个圆的圆心坐标为(xi,yi),半径为Ri。
- 你的任务是求最小的正实数k,使得把每个圆的半径变为原来的k倍后(即:第i个圆半径变为kRi,圆心位置不变),长方形将被这些圆完全覆盖。
- 换句话说,长方形内部或边界上的任意点均至少在一个圆的内部或边界上。
- 输入格式
- 输入第一行包含三个整数n, L, W(1<=n<=50,1<=L,W<=1000),即圆的个数、长方形的长和宽。
- 以下n行,每行三个不超过1000的正整数xi, yi和Ri。
- 输出格式
- 仅一行,包含一个实数k,保留小数点后三位。
- 样例输入
- 1 2 2
- 1 1 1
- 样例输出
- 1.414*/
-
- public static void main(String[] args) {
-
- /*输入格式我就不写了
- * 样例输入
- 1 2 2
- 1 1 1
- 样例输出
- 1.414*/
- System.out.println(getAllMinK(new int[][]{{1,1,1,2,2}}));
-
- /* 样例输入
- 3 2 2
- 1 1 1
- 1 1 2
- 样例输出
- 0.707
- * */
- System.out.println(getAllMinK(new int[][]{{1,1,1,2,2},{1,1,2,2,2}}));
- }
-
- public static double getAllMinK(int[][] circle) {
- double minK = getMinK(circle[0]);
-
- for(int i=0; i<circle.length; i++) {
- double k = getMinK(circle[i]);
- if(k<minK)
- minK = k;
- }
- return (int)(minK*1000)/1000.0;
- }
-
- /*circle[] x,y,r,l,w*/
- public static double getMinK(int... circle) {
- double r00 = getC(circle[0]-0 ,circle[1]-0);
- double r0w = getC(circle[0]-0 ,circle[1]-circle[4]);
- double rl0 = getC(circle[0]-circle[3] ,circle[1]-0);
- double rlw = getC(circle[0]-circle[3] ,circle[1]-circle[4]);
-
- /*此最小半径保证此圆完全覆盖长方形*/
- double rMax = getMax(r00, r0w, rl0, rlw);
-
- /*此圆最小k*/
- return rMax/circle[2];
- }
-
- /*勾股定理,你懂的*/
- public static double getC(int a, int b) {
- return Math.sqrt(a*a+b*b);
- }
-
- /*求给定数组的最大元素*/
- public static double getMax(double... numble) {
- int length = numble.length;
- double max = numble[0];
- for(int i=1; i<length; i++) {
- if(numble[i]>max)
- max = numble[i];
- }
- return max;
- }
- }
复制代码 下午发的代码中,这个函数有问题,修改如下:- public static double getAllMinK(int[][] circle) {
- double minK = getMinK(circle[0]);
-
- for(int i=0; i<circle.length; i++) {
- double k = getMinK(circle[i]);
- if(k<minK)
- minK = k;
- }
- return (int)(minK*1000)/1000.0;
- }
复制代码
作者: 柏占肖 时间: 2012-10-10 17:57
寇龙飞 发表于 2012-10-9 00:04 
我来了,求测试数据。
你只做了一个圆的情况啊,这个就很简单了,关键是题目中说的可以有多个圆呢,如果我给你3个圆,你把这3个圆的圆心到这个矩形的4个顶点的距离求出来再从中取个最大的值来做为最小半径,那这样就错了
作者: 寇龙飞 时间: 2012-10-10 18:22
柏占肖 发表于 2012-10-10 17:57 
你只做了一个圆的情况啊,这个就很简单了,关键是题目中说的可以有多个圆呢,如果我给你3个圆,你把这3个 ...
- for(int i=0; i<circle.length; i++) {
- double k = getMinK(circle[i]);
- if(k>minK)
- minK = k;
- }
复制代码 我知道你题目的要求,这里写了for循环的亲。
所以,我发代码时也说了,要测试数据啊,你给三个圆的数据就是了。
作者: 柏占肖 时间: 2012-10-10 18:30
寇龙飞 发表于 2012-10-10 18:22 
我知道你题目的要求,这里写了for循环的亲。
所以,我发代码时也说了,要测试数据啊,你给三个圆的数据就 ...
再给简单点,两个圆,一个大圆,它已经把这个矩形覆盖了,再给个小圆,它没有把矩形覆盖,按你的这个算法算出来就是它们的半径还需要放大,这很明显就错了
作者: 寇龙飞 时间: 2012-10-10 20:42
柏占肖 发表于 2012-10-10 18:30 
再给简单点,两个圆,一个大圆,它已经把这个矩形覆盖了,再给个小圆,它没有把矩形覆盖,按你的这个算法 ...
嗯。了解。是我那个getAllMinK函数中变量minK初始化错误,导致if(k与minK)的判断逻辑错误。
现在偶了。。。14楼代码
作者: 柏占肖 时间: 2012-10-10 21:41
寇龙飞 发表于 2012-10-10 20:42 
嗯。了解。是我那个getAllMinK函数中变量minK初始化错误,导致if(k与minK)的判断逻辑错误。
现在偶了。 ...
不行啊,你的这个思想不对,以你的算法算出和结果就是我给你N个圆,半径改变后,至少有一个圆是把整个矩形都覆盖了的,但是题目并不是这个意思,打个比方,就好比树下的阴影,那么大一块阴影并不是因为哪一片叶子挡住了阳光而形成的,而是因为很多叶子拼凑在一起而形成的,在这里,圆就好比叶子,矩形就好比树下的阴影。
这个题还是有一些难度的,等我把视频面试过了就来整它了,个人觉得这个要先把倍数的取值范围求出来,然后再用折半法来找出最小且满足题目要求的倍数
作者: 寇龙飞 时间: 2012-10-11 11:56
柏占肖 发表于 2012-10-10 21:41 
不行啊,你的这个思想不对,以你的算法算出和结果就是我给你N个圆,半径改变后,至少有一个圆是把整个矩 ...
“换句话说,长方形内部或边界上的任意点均至少在一个圆的内部或边界上。”
怎么说
作者: 柏占肖 时间: 2012-10-11 13:09
寇龙飞 发表于 2012-10-11 11:56 
“换句话说,长方形内部或边界上的任意点均至少在一个圆的内部或边界上。”
如果用多个圆来覆盖,在矩形内部可能就有圆与圆的重合,那么这时矩形内部的的有些点可能就同时在多个圆的内部或边界上了,题目中说至少,也就是说矩形中的每一点都要被覆盖
-
2.jpg
(17.64 KB, 下载次数: 62)
初始
-
2.png
(7.46 KB, 下载次数: 66)
放大2.575倍后刚好完全覆盖
作者: 王震阳老师 时间: 2012-10-11 13:44
我看看。。
作者: 王威 时间: 2012-10-11 16:26
说实话看懂这个题目还要花点时间呢
作者: 寇龙飞 时间: 2012-10-11 20:44
柏占肖 发表于 2012-10-11 13:09 
如果用多个圆来覆盖,在矩形内部可能就有圆与圆的重合,那么这时矩形内部的的有些点可能就同时在多个圆的 ...
no
不是多个圆最小的共同努力下覆盖长方形,而是最小努力下某一个最合适的圆覆盖长方形
作者: 柏占肖 时间: 2012-10-11 21:37
寇龙飞 发表于 2012-10-11 20:44 
no
不是多个圆最小的共同努力下覆盖长方形,而是最小努力下某一个最合适的圆覆盖长方形 ...
你理解错了 照你那样理解的话这题也太简单了
作者: 寇龙飞 时间: 2012-10-11 22:12
柏占肖 发表于 2012-10-11 21:37 
你理解错了 照你那样理解的话这题也太简单了
不管题目难易,咱主要是看满足题目覆盖的条件是什么。
作者: 柏占肖 时间: 2012-10-11 22:30
寇龙飞 发表于 2012-10-11 22:12 
不管题目难易,咱主要是看满足题目覆盖的条件是什么。
我上面贴了两张图的 你好好看看吧 我以为是百度之星的题呢 结果我一个耍得好的说是ITAT的最后一道题 这题真的不是你理解的那样啊
作者: 寇龙飞 时间: 2012-10-11 22:46
柏占肖 发表于 2012-10-11 22:30 
我上面贴了两张图的 你好好看看吧 我以为是百度之星的题呢 结果我一个耍得好的说是ITAT的最后一道题 ...
嗯。终于想通了,你说的是对的。群圆覆盖长方形。
作者: 柏占肖 时间: 2012-10-11 22:49
寇龙飞 发表于 2012-10-11 22:46 
嗯。终于想通了,你说的是对的。群圆覆盖长方形。
呵呵……有些大赛的题就是不好读,ACM的更是 像文言文一样
作者: 寇龙飞 时间: 2012-10-11 23:35
柏占肖 发表于 2012-10-11 22:49 
呵呵……有些大赛的题就是不好读,ACM的更是 像文言文一样
嗯。我还是没学好知识,理解力不够。悔不当初,只能现在努力勒。
作者: 柏占肖 时间: 2012-10-12 00:38
寇龙飞 发表于 2012-10-11 23:35 
嗯。我还是没学好知识,理解力不够。悔不当初,只能现在努力勒。
嗯 加油
作者: 柏占肖 时间: 2012-10-12 00:38
寇龙飞 发表于 2012-10-11 23:35 
嗯。我还是没学好知识,理解力不够。悔不当初,只能现在努力勒。
嗯 加油
欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) |
黑马程序员IT技术论坛 X3.2 |