hhu1037 Calvin's Experiment Floyd判最小环 未完待续

1037: Calvin's Experiment

时间限制: 1 Sec   内存限制: 128 MB
提交: 14   解决: 5
[ 提交][ 状态][ 讨论版]

题目描述

Calvin Neo is a acmer in HHU, but he is also a civil engineer. Civil Engineering is about moving bricks(搬砖), however it involves many scientific theories and experiments.
Calvin designed a experiment to evaluate the attribute of soil in a construction site(工地), the construction site can be viewed as a 2-dimension Cartesian Coordinate System(平面直角坐标系), this experiment includes 2 steps:
1. Calvin choose some point and use CDT(a geological survey method) to test the attribute of soils at that point and use them to work out some assumptions.
2. Calvin choose n tested points from step 1 and get a polygon(多边形). he start from point 1 and go along the polygon, visit every point once and finally back to point 1. while walking, Calvin use geological radar(地质雷达) to detect the attribute of soils beneath to prove his assumptions
however life in Calvin's construction site is hard, there are ways between only several tested points and the geological radar is expensive so that Calvin should find a polygon with the shortest length(周长).
Calvin is a acmer and he definitely knows the answer, but he is busy moving bricks now, so he ask you for help.

输入

there are multiple test cases, every test case has multiple lines:
line 1: 2 integers n(less than 233), m(less than 500, for 70% cases, m less than 200)
following n lines: 2 integers x, y stand for the coordinate of points(start from 1), 0 <= (x, y) <= 1000
following m lines: 2 integers u, v means there is a path between u and v

输出

for every test case print one line, which is the minimum length(周长)
print "impossible" in one line if there is no such polygon
hint: you should use "%.2f\n" to print

样例输入

9 6
0 0
0 1
0 2
1 0
1 1
1 2
2 0
2 1
2 2
1 3
1 7
7 9
3 9
2 5
4 5
1 0
1 1

样例输出

4.00
impossible

提示

for case 1, choose point 1, 2, 4, 5 as a polygon whose length is 4.00

来源

这题不愧是咱们学校比赛防ak的题目。。。。我wa了好久参考了学长的代码才对的。。。

我靠。。。垃圾csdn。。。为什么老吞我博客啊啊啊啊啊啊啊啊啊。这已经是我第三遍写了。。。

不想写了。。。。。

题意:

骆融臻是个土木工程师,忙于搬砖。他在工地生活困难,有天他想测试工地的土壤,该工地上有n个点,他想从1号点出发经过几个点测试土壤最后回到1号点。现在问我们是否能完成他的测试,如果能输出走路的最短距离

题目会给n个点每个点的坐标,还有m个点对,代表两点之间存在一条路

因为这是一个平面直角坐标系,所以我们不能把题目给的m个路当成最终的连通路,在这两点连线上的点也都是连通的。

暂且不讲我还没有理解floyd求最小环的。。。这个处理也是比较麻烦的

我在感悟感悟,先放上代码:

再吞我博文自杀

#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <map>
#include <vector>
#include <queue>
using namespace std;
#define INF 0x3f3f3f3f
const int maxn = 250;
const double killme = 1e7;
const double eps = 1e-8;
double min_loop;
double mp[maxn][maxn];
double dis[maxn][maxn];
pair<double, double > save[maxn];
vector<int> final[510];

int n,m;
void init(){
    int i,j;
    for(i=1;i<=n;i++){
        for(j=1;j<=n;j++){
            if(i==j){
                mp[i][j] = 0.0f;
                dis[i][j] = 0.0f;
            }else{
                mp[i][j] = INF;
                dis[i][j] = INF;
            }
        }
    }
    for(i=1;i<=m;i++){
        final[i].clear();
    }
}
bool online(int x,int y,int x1,int y1,int x2,int y2){
    int min_x = min(x1,x2),max_x = max(x1,x2);
    int min_y = min(y1,y2),max_y = max(y1,y2);
    if(min_x>x||x>max_x||y<min_y||y>max_y){
        return false;
    }
    if((y1 - y2) *  (x - x1) == (y - y1) * (x1 - x2)){
        return true;
    }
    return false;
}
bool floyd(){
    min_loop = INF;
    int i,j,k;
    for(k=1;k<=n;k++){
        for(i=1;i<k;i++){
            for(j=i+1;j<k;j++){
                if(min_loop>mp[i][j]+dis[i][k]+dis[k][j]){
                    min_loop = mp[i][j] + dis[i][k]+dis[k][j];
                }
            }
        }
        for(i=1;i<=n;i++){
            for(j=1;j<=n;j++){
                mp[i][j] = min(mp[i][j],mp[i][k]+mp[k][j]);
            }
        }
    }
    if(min_loop>killme){
        return  false;
    }else{
        return true;
    }
 
}
bool compare(int a,int b){
    if(abs(save[a].first-save[b].second)==0){
        return save[a].second<save[b].second;
    }
    return save[a].first<save[b].first;
}
int main(){
    //cout<<online(18, 97, 99, 67, 18, 97)<<endl;
    int i,j;
    while (~scanf("%d%d",&n,&m)) {
        double a,b;
        for(i=1;i<=n;i++){
            scanf("%lf%lf",&a,&b);
            save[i] = make_pair(a, b);
        }
        init();
        int u,v;
        for(i=1;i<=m;i++){
            scanf("%d%d",&u,&v);
            for(j=1;j<=n;j++){
                if(online(save[j].first, save[j].second, save[u].first, save[u].second, save[v].first, save[v].second)){
                    final[i].push_back(j);
                }
            }
            sort(final[i].begin(), final[i].end(), compare);
            for(j=0;j < final[i].size()-1;j++){
                u = final[i][j];
                v = final[i][j+1];
                mp[u][v] = min(mp[u][v] , sqrt(pow(save[u].first-save[v].first,2)+pow(save[u].second-save[v].second,2)));
                mp[v][u] = mp[u][v];
                dis[u][v] = mp[u][v];
                dis[v][u] = mp[u][v];
            }
            
        }
        if(floyd()){
            printf("%.2lf\n",min_loop);
        }else{
            printf("impossible\n");
        }
    }
    return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值