POJ 3714 Raid
2013-07-19 11:31
281 查看
//POJ 3714 Raid //AC by warteac //2013-7-19 /* 法一:先排序,然后依次向后找最小距离,并且剪枝 重点是,不需要指定找 人到站点或是站点到人的距离,把所有的都看成点,就找两点最短距离即可 为了区别用flag标记,求距离时判断flag是否相同。 6764K 3579MS C++ 2090B 2013-07-19 11:44:37 法二:二分是高效算法; 重点是,合并的时候,求最短距离横跨左右两边的情况,有一个剪枝的动作,不加依然会超时,详见代码 TLE: 重复调用函数导致超时,不是算法的问题,详见代码 6768K 2922MS C++ 2725B 2013-07-19 11:46:29 */ #include<iostream> #include<cstdio> #include<cmath> #include<vector> #include <iomanip> #include<algorithm> using namespace std; const double eps = 1e-5; const double MAXLEN = 1000000000.0; struct posi{ double x; double y; bool flag; //0 is agent,1 is raid }; vector <posi> p; int num; double min_length; double length(posi p1, posi p2){ if(p1.flag != p2.flag) return sqrt((p2.x - p1.x)*(p2.x - p1.x)+(p2.y - p1.y)*(p2.y - p1.y)); else return MAXLEN; } bool cmp(posi p1, posi p2){ if(fabs(p1.x - p2.x) < eps){ return p1.y < p2.y; }else{ return p1.x < p2.x; } } //////////////////法一///////////////////////////////// /*double getMinLength(int i){ double min = MAXLEN; for(int j = i+1; j < 2*num; j++){ if(p[i].flag != p[j].flag){ double temp = length(p[i],p[j]); if(temp - min < eps){ min = temp; } else if(fabs(p[i].x - p[j].x) > min)//如果不加这句if(),有BUG,但POJ没有检查出来,具体测试数据见下面 break; } } return min; }*/ ////////////////////法一结束///////////////////////////// ////////////////////法二//////////////////////////////// double getMinLength(int x, int y){ if(y - x <= 2){ double len,minlen = MAXLEN; for(int i = x; i < y; i++) for(int j = x+1; j < y; j++){ len = length(p[i],p[j]); //minlen <?= len; if(len < minlen) minlen = len; } return minlen; }else{ double r,result = MAXLEN; int i,j; int m = (x + y) / 2;//第一步:划分 //result = getMinLength(x,m) < getMinLength(m,y) ? getMinLength(x,m) : getMinLength(m,y);//第二步:递归解决子问题 //TLE: 上式中调用getMinLength()四次,在递归次数庞大时就会导致超时了 //解决办法,用两个变量Llen,Rlen 保存函数的调用值 double Llen,Rlen; Llen = getMinLength(x,m); Rlen = getMinLength(m,y); result = Llen < Rlen ? Llen : Rlen;//第二步:递归解决子问题 for(i = m-1; i >= x; i--){//第三步:合并 if(fabs(p[m].x - p[i].x) > result) break;//剪枝 for(j = m; j < y; j++){ if(fabs(p[m].x - p[j].x) > result) break;//剪枝 r = length(p[i],p[j]); //result <?= r; if(result > r) result = r; } } return result; } } /////////////////////法二结束/////////////////////////////// int main(){ int n,i,j; cin >> n; while(n--){ posi t; cin >> num; p.clear(); min_length = MAXLEN; for(i = 0; i < num; i++){ cin >> t.x >> t.y; t.flag = 0;//agent p.push_back(t); } for(i = 0; i < num; i++){ cin >> t.x >> t.y; t.flag = 1;//raid p.push_back(t); } sort(p.begin(),p.end(),cmp); //////////////////法一/////////////////////////// /* for(int k = 0 ;k < p.size();k++){ } for(j = 0; j < 2*num-1; j++){ double mlen = getMinLength(j); if(mlen < min_length) min_length = mlen; }*/ //////////////////法一结束///////////////////////////// //////////////////法二////////////////////////////// min_length = getMinLength(0,p.size()); //////////////////法二结束////////////////////////// cout <<setiosflags(ios::fixed); cout << setprecision(3); cout << min_length << endl; } return 0; } /* 测试BUG的数据 INPUT: 1 3 0 0 13 13 15 15 2 5 4 0 4 -6 OUTPUT:(right) 4.000 OUTPUT:(wrong) 5.385 */
相关文章推荐
- poj 3714 Raid(平面最近点对)
- POJ 3714 Raid
- 【解题报告】 POJ 3714 Raid -- 点对最小距离 + 分治法
- poj3714 Raid(分治法…
- 【POJ 3714】Raid
- poj 3714 Raid
- poj 3714 raid
- poj 3714 Raid
- POJ 3714 Raid 最近点对 扫描线
- 1.11 POJ 3714 Raid
- POJ 3714 Raid
- POJ 3714 Raid
- POJ_3714_Raid(平面最近点对)
- POJ 3714 Raid(计算几何の最近点对)
- POJ 3714 Raid
- POJ 3714 Raid 最近点对
- POJ 3714 raid
- POJ 3714 Raid(平面最近点对,不同类型点之间)
- POJ 3714 Raid(分治)
- POJ 3714 Raid