poj-3072 Robot ***

/*
* Graph-poj-3072.cpp
*
* Created on: 2011-11-20
*
* dijkstra..
*
* 分别用 STL 的 heap操作 和 普通的数组操作 实现
*
*
*/
#include <cstdio>
#include <cmath>
#include <cstring>
using namespace std;

const int maxn = 20 + 2;
const double pi = atan(1.0) * 4;
const double eps = 1e-9;
const double inf = 100000000;
int r, n;
bool vis[maxn] = {};

struct SNode{
int x, y;
double degree;
double dist;
};
SNode node[maxn];

//两点连线和x轴的夹角
double getDegree(SNode *cur, SNode *next){
int tmpx = next->x - cur->x;
int tmpy = next->y - cur->y;
double degree = atan2((double)tmpy, (double)tmpx);

// if(degree < -eps) degree += 2 * pi; //化为[0..2*pi]...这里可写可不写。

return degree;
}

//从cur点的当前方向转到next点的角度, 注意不超过 pi
double rotateDegree(SNode *cur, SNode *next, double &degree){
double nextDegree = getDegree(cur, next);
degree = nextDegree;

double ans = fabs(nextDegree - cur->degree);
if(ans > pi + eps) ans = 2 * pi - ans;

return ans;
}

//初始化
void ini(){
memset(vis, 0, sizeof(vis));

for(int i=0; i<n; i++){
node[i].dist = inf;
}
node[0].dist = 0;
node[0].degree = getDegree(&node[0], &node[n-1]);
}

//更新个点的dist域和degree域
void update(SNode *cur, SNode *next){
double dist;
double tmpDist = sqrt(fabs((cur->x - next->x) * (cur->x - next->x)*1.0
+ (cur->y - next->y) * (cur->y - next->y)*1.0));

//超过r
if(tmpDist > r + eps)
return;

//
double tmpDegree;
//距离,注意角度化为 °
dist = rotateDegree(cur, next, tmpDegree) * 180 / pi + tmpDist + cur->dist;
if(dist < next->dist - eps){
next->dist = dist;
next->degree = tmpDegree;
}
}


void dijkstra(){
double min = inf;
int cur = -1;

ini();

while(!vis[n-1]){
//找到当前最小距离的点
cur = -1, min = inf;
for(int i=0; i<n; i++){
if(!vis[i] && node[i].dist < min - eps){
min = node[i].dist;
cur = i;
}
}
//更新完了
if(cur == -1) break;

vis[cur] = true;

//更新
for(int i=0; i<n; i++){
if(vis[i]) continue;
update(&node[cur], &node[i]);
}
}


//结果
if(!vis[n-1])
printf("impossible\n");
else
printf("%d\n", (int)(node[n-1].dist + 0.5));

}



int main(){
while(scanf("%d%d", &r, &n)){
if(r == -1) return 0;

for(int i=0; i<n; i++){
scanf("%d%d", &node[i].x, &node[i].y);
}

dijkstra();
}

return 0;
}

  

  

//用 STL 的 heap

  

/*
* Graph-poj-3072.cpp
*
* Created on: 2011-11-20
*/
#include <cstdio>
#include <cmath>
#include <vector>
#include <algorithm>
using namespace std;

const int maxn = 20 + 2;
const double pi = atan(1.0) * 4;
const double eps = 1e-9;
const double inf = 100000000;
int r, n;

struct SNode{
int x, y;
double degree;
double dist;
};
SNode node[maxn];


//实现最小堆
bool cmp(SNode *lhs, SNode *rhs){
return lhs->dist > (rhs->dist + eps);
}

double getDegree(SNode *cur, SNode *next){
int tmpx = next->x - cur->x;
int tmpy = next->y - cur->y;
double degree = atan2((double)tmpy, (double)tmpx);
// if(degree < -eps) degree += 2 * pi;

return degree;
}


double rotateDegree(SNode *cur, SNode *next, double &degree){
double nextDegree = getDegree(cur, next);
degree = nextDegree;

double ans = fabs(nextDegree - cur->degree);
if(ans > pi + eps) ans = 2 * pi - ans;

return ans;
}

void ini(vector<SNode *> &v){
for(int i=0; i<n; i++){
node[i].dist = inf;
v.push_back(&node[i]);
}
node[0].dist = 0;
node[0].degree = getDegree(&node[0], &node[n-1]);

make_heap(v.begin(), v.end(), cmp);
}

bool update(SNode *cur, SNode *next){
double dist;
double tmpDist = sqrt(fabs((double)(cur->x - next->x) * (cur->x - next->x)
+ (cur->y - next->y) * (cur->y - next->y)));

if(tmpDist > r + eps)
return false;

bool flag = 0;
double tmpDegree;
dist = rotateDegree(cur, next, tmpDegree) * 180 / pi + tmpDist + cur->dist;
if(dist < next->dist - eps){
next->dist = dist;
next->degree = tmpDegree;
flag = 1;
}
return flag;
}

void dijkstra(){
vector<SNode *> v;
vector<SNode *>::iterator iter;
ini(v);

SNode *cur;
while(!v.empty()){
pop_heap(v.begin(), v.end(), cmp);
cur = v.back();

//何时退出循环。。。 这里WA了无数遍。。 囧
if(cur->dist >= inf - eps) break;

v.pop_back();

for(iter=v.begin(); iter!=v.end(); iter++){
update(cur, *iter);
}
//因为UPDATE了数据, 所以要重新建堆 (所以用heap操作慢一些。。 不如直接用数组)
make_heap(v.begin(), v.end(), cmp);
}


if(node[n-1].dist >= inf - eps)
printf("impossible\n");
else
printf("%d\n", (int)(node[n-1].dist + 0.5));

}



int main(){
while(scanf("%d%d", &r, &n)){
if(r == -1) return 0;

for(int i=0; i<n; i++){
scanf("%d%d", &node[i].x, &node[i].y);
}

dijkstra();
}

return 0;
}



 

  

 

 

 

posted on 2011-11-20 13:28  龙豆  阅读(1174)  评论(0编辑  收藏  举报

导航