HDU 1245 Saving James Bond

链接:

http://acm.hdu.edu.cn/showproblem.php?pid=1245


题目:

Saving James Bond

Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 1066    Accepted Submission(s): 186


Problem Description
This time let us consider the situation in the movie "Live and Let Die" in which James Bond, the world's most famous spy, was captured by a group of drug dealers. He was sent to a small piece of land at the center of a lake filled with crocodiles. There he performed the most daring action to escape -- he jumped onto the head of the nearest crocodile! Before the animal realized what was happening, James jumped again onto the next big head... Finally he reached the bank before the last crocodile could bite him (actually the stunt man was caught by the big mouth and barely escaped with his extra thick boot).
Assume that the lake is a 100×100 square one. Assume that the center of the lake is at (0,0) and the northeast corner at (50,50). The central island is a disk centered at (0,0) with the diameter of 15. A number of crocodiles are in the lake at various positions. Given the coordinates of each crocodile and the distance that James could jump, you must tell him whether he could escape.If he could,tell him the shortest length he has to jump and the min-steps he has to jump for shortest length.
 

Input
The input consists of several test cases. Each case starts with a line containing n <= 100, the number of crocodiles, and d > 0, the distance that James could jump. Then one line follows for each crocodile, containing the (x, y) location of the crocodile. Note that x and y are both integers, and no two crocodiles are staying at the same position. 
 

Output
For each test case, if James can escape, output in one line the shortest length he has to jump and the min-steps he has to jump for shortest length. If it is impossible for James to escape that way, simply ouput "can't be saved".
 

Sample Input
  
  
4 10 17 0 27 0 37 0 45 0 1 10 20 30
 

Sample Output
  
  
42.50 5 can't be saved
 

Author
weigang Lee
 

Recommend
Ignatius.L
 

分析与总结:


本题建图是关键:

1. 把整个这个岛看作为点0,由于中间的岛的直径为15,那么每只鳄鱼能否从岛上跳上需要特判,如果某只鳄鱼如果距离中心点(0,0)为dis,那么只要dis-7.5<=d, 就可以建立这条边的关系


2. 把整个岸边看为点n+1, 由于每只鳄鱼距离岸上的距离也不同,所以也需要特判。 取每只鳄鱼距离四个岸边最短的那个距离为权值。求距离岸边的方法: 我们知道湖的范围为(i,j),-50<i=j<50, 对于鳄鱼坐标(x,y),   50-max(abs(x), abs(y))便是这个坐标距离岸边最短的距离。


3. 本题很难发现的Trick: 

   (1) 对于每只鳄鱼的坐标,有可能是不合法的,可能会是在中间的岛上,也能是在岸上,所以需要先过滤判断。

   (2) 如果James Bond可以跳的距离d大于42.50(岛到岸边的距离),那么可以直接跳到岸上,步数为1                                     


建好图之后,用最短路算法计算即可。

另外,由于还要计算步数,再增加一个权值step,都赋值为1即可


代码: 

用Dijkstra

#include<cstdio>
#include<cstring>
#include<math.h>
#include<iostream>
using namespace std;

typedef double Type;
const int VN = 205;
const int INF=0x7fffffff/2;

int n,size;
double D;
double x[VN];
double y[VN];
Type d[VN];
Type w[VN][VN];
int s[VN][VN];
int step[VN];
bool vis[VN];
int pos;
int end[VN];

double getDist(int i, int j){
    return sqrt(pow(x[i]-x[j],2)+pow(y[i]-y[j],2));
}
void init(){
    pos = 0; 
    size=0;
    x[0] = y[0] = 0;
}
double bankDist(double i, double j){ //增加岸边上的点
    return 50*1.0-max(fabs(i), fabs(j));       
}

void Dijkstra(int src){
    memset(vis, 0, sizeof(vis));
    for(int i=0; i<=n; ++i) d[i]=INF,step[i]=INF;
    step[src] = d[src] = 0;
    for(int i=0; i<=n; ++i){
        int u=-1;
        for(int j=0; j<=n; ++j)if(!vis[j]){
            if(u==-1 || d[j]<d[u]) u=j;
        }
        vis[u] = 1;
        for(int j=0; j<=n; ++j)if(!vis[j]){
            Type tmp = d[u]+w[u][j];
            int tmp_s = step[u]+s[u][j];
            if(d[j]>tmp){
                d[j]=tmp; 
                step[j]=tmp_s;
            }
            else if(d[j]==tmp&&step[j]>tmp_s)
                step[j]=tmp_s;
        }
    }
}

int main(){
    double a,b;
    while(~scanf("%d%lf",&n,&D)){
        if(D>=42.5){
            puts("42.50 1");
            continue;
        } 
        init();
        for(int i=1; i<=n; ++i){
            scanf("%lf%lf",&a,&b);
            if(fabs(a)<=7.5&&fabs(b)<=7.5
              || fabs(a)>50 || fabs(b)>50)continue;
            x[++size]=a, y[size]=b;
        }
        n = size+1;
        for(int i=0; i<=n; ++i){
            w[i][i] = INF;
            s[i][i] = 0;
            for(int j=i+1; j<=n; ++j){
                w[i][j]=w[j][i]=INF;
                s[i][j]=s[j][i]=1;
            }
        }
        for(int i=1; i<=size; ++i){
            double dis = getDist(0,i);
            if(dis-7.5<=D){ // 从小岛可以跳上的点,整个小岛为点0
                w[0][i] = w[i][0] = dis-7.5;
            }
             // 从该点能否跳到岸上
            dis = bankDist(x[i],y[i]);
            if(dis<=D){
                w[i][n]=w[n][i]=dis;
            }
            for(int j=i+1; j<=size; ++j){
                dis = getDist(i,j);
                if(dis<=D){
                    w[i][j] = w[j][i] = dis;
                }
            }
        }
        Dijkstra(0);
        if(d[n]!=INF)printf("%.2f %d\n",d[n],step[n]);
        else puts("can't be saved");
    }
    return 0;
}

 
 

——  生命的意义,在于赋予它意义。

          
     原创 http://blog.csdn.net/shuangde800 , By   D_Double  (转载请标明)


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值