您的位置:首页 > 大数据 > 人工智能

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
*/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: