hdu 2482

神技能 缩点

题意:
给出一幅地图 起点和终点(要按题中所说的规则转化成实际坐标)
给出一些公共汽车站 以及公车行进的线路
如果起点和终点距离不超过2000 则输出walk there
如果在离起点1000米内有车站 离终点1000米内有车站
并且可以从起点的车站坐bus到终点的车站 则输出最少换乘次数
否则输出take a taxi

#include <iostream>
#include <cstdio>
#include <cstring>
#include <map>
#include <vector>
using namespace std;
#define N 5010
int ans[110][110];
struct node{
    int x,y;
}data[N];
void dis(char s[],int &x,int &y) {
    double ans = 10240/2.0,a = 0,b = 0,bili = ans/10;
    for(int i = 0; i < 8; i++) {
        if(s[i] == '0') i = i;
        else if(s[i] == '1') b = ans+b;
        else if(s[i] == '2') a = ans+a;
        else a = a+ans,b = b+ans;
        ans = ans/2.0;
        bili = ans/10;
    }
    x = a+x*bili;
    y = b+y*bili;
}
double dist(node a,node b) {
    return (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y);
}
void solve() {
    int n,m,k;scanf("%d",&n);
    char s[30],s1[30];
    map<string,int>mp; n = n + 2;
    for(int i = 2; i < n; i++) {
        scanf("%s %d %d",s,&data[i].x,&data[i].y);
        mp[s] = i;
    }
    scanf("%d",&m);
    int x,y; vector<int>vc[110];
    m = m + 2;
    for(int i = 2; i < m; i++) {
        scanf("%d",&x);
        while(x--) {
            scanf("%s",&s);
            y = mp[s];
            vc[i].push_back(y);
        }
    }
    if(dist(data[0],data[1]) < 4000000) {
        printf("walk there\n");
        return ;
    }
    for(int i = 0; i < m; i++) for(int j = 0; j < m; j++) ans[i][j] = N;
    for(int i = 2; i < m; i++)
      for(int j = 2; j < m; j++)
        if(i!=j) {
            bool flag = 0;
            for(int k = 0; k < vc[i].size(); k++)
              for(int z = 0; z < vc[j].size(); z++)
                if(vc[i][k] == vc[j][z]) 
                  flag = 1;
            if(flag) ans[i][j] = ans[j][i] = 1;
        } // 除了端点之外的边
    for(int i = 2; i < m; i++) {  // 起点构边
        for(int j = 0; j < vc[i].size(); j++)
          if(dist(data[0],data[vc[i][j]]) <= 1000000)
            ans[0][i] = 1;
    }
    for(int i = 2; i < m; i++) {   // 终点构边
        for(int j = 0; j < vc[i].size(); j++)
          if(dist(data[1],data[vc[i][j]]) <= 1000000) {
            ans[1][i] = ans[i][1] = 1;
          }
    }   
    for(int k = 0; k < m; k++)
      for(int i = 0; i < m; i++)
        for(int j = 0; j < m; j++)
          ans[i][j] = min(ans[i][j],ans[i][k]+ans[k][j]);
    if(ans[0][1] >= N) printf("take a taxi\n");
    else printf("%d\n",ans[0][1]-1);
}
int main() {
    int t;scanf("%d",&t);
    while(t--) {
        char s[20]; scanf("%s %d %d",&s,&data[0].x,&data[0].y);
        dis(s,data[0].x,data[0].y);
        scanf("%s %d%d",&s,&data[1].x,&data[1].y);
        dis(s,data[1].x,data[1].y);
        solve();
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值