CODEVS 1041Car的旅行路线

声明:源代码从iwtwiioi_2处转载,这是 原文链接 。我在此代码的基础上做进一步的说明解释。

#include <iostream>
#include <algorithm>
#include <cstring>
#include <iomanip>
#include <cmath>
using namespace std;
const double oo = 10000000;
//城市的飞机场 (x-1)*4+1代表第x个城市开始的飞机场下标
#define CTOA(x) (((x-1)<<2)+1)
//距离
#define DISTANCE(x1,y1,x2,y2) ((double)sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)))
//此题我用FLOYD做的,因为数据太弱,过了
//每个飞机场为一个节点,答案就是A到B所有的路线最短路的最小值
struct city
{
    int x[4], y[4];
}ct[105];

double node[4050][4050];
double T;
int s, t, A, B, N, i, j, k, l, temp, airport, tx[3], ty[3];
//至于计算第四个点,由数学知识我们可以知道,相互垂直的两条直线的斜率互为负倒数,所以我们只要每次计算AB、BC的斜率。
//如果不满足条件,那么将A、B、C的坐标分别赋值为B、C、A,这样不断迭代,直到AB、BC垂直,这样就能计算出第四个点的坐标。
//还要注意一个问题,如果AB或者BC与坐标轴垂直,需要单独讨论这种情况,因为被除数不能为零。
//(1) 首先判断直角的位置:
//因为从测试数据文件中读入的三个点的坐标是无序的,因此需判断直角的位置,然后在计算第四个点的坐标。
//对于线段L1、L2,如果(x1-x2)*(x3-x2)+(y1-y2)*(y3-y2)=0,那么L1 ⊥ L2。
//(2) 计算(x4,y4):
//由x4-x3=x1-x2得x4=x1-x2+x3,同样的y4=y1-y2+y3
void getfour(int c) //获取第四个城市
{
    memcpy(tx, ct[c].x, sizeof(tx));
    memcpy(ty, ct[c].y, sizeof(ty));
    int tt;
    while((tx[0]-tx[1])*(tx[2]-tx[1])+(ty[0]-ty[1])*(ty[2]-ty[1]))
    {
        tt = tx[0]; tx[0]=tx[1]; tx[1]=tx[2]; tx[2]=tt;
        tt = ty[0]; ty[0]=ty[1]; ty[1]=ty[2]; ty[2]=tt;
    }
    ct[c].x[3] = tx[0]-tx[1]+tx[2];
    ct[c].y[3] = ty[0]-ty[1]+ty[2];}

int main()
{
    cin >> N;
    while(N--)
    {
        cin >> s >> t >> A >> B;
        //注意A=B的情况,也就是出发的城市就是结束的城市,这是要直接输出‘0.0’;
        if(A == B) {cout << "0.0\n";continue;}
        //s<<2表示飞机场数量,即s*4
        airport = s << 2;
        for(i = 1; i <= airport; i++)
            for(j = 1; j <= airport; j++)
                node[i][j] = oo; //初始化

        for(i = 1; i <= s; i++)
        {
            for(j = 0; j < 3; j++)
                cin >> ct[i].x[j] >> ct[i].y[j];
            cin >> T;
            getfour(i);
            //初始同一城市飞机场的花费
            for(j = 0; j < 4; j++)
                for(k = 0; k < 4; k++)
                    if(j != k)
                        node[CTOA(i)+j][CTOA(i)+k] = DISTANCE(ct[i].x[j], ct[i].y[j], ct[i].x[k], ct[i].y[k]) * T;
        }

        //初始不同城市飞机场的花费
        for(i = 1; i <= s; i++)
            for(j = 1; j <= s; j++)
                if(i != j)
                    for(k = 0; k < 4; k++)
                        for(l = 0; l < 4; l++)
                            node[CTOA(i)+k][CTOA(j)+l] = (DISTANCE(ct[i].x[k], ct[i].y[k], ct[j].x[l], ct[j].y[l]) * t);

        //Floyd
        for(k = 1; k <= airport; k++)
            for(i = 1; i <= airport; i++)
                for(j = 1; j <= airport; j++)
                    node[i][j] = min(node[i][j], node[i][k]+node[k][j]);

        //A到B所有的路线最短路的最小值
        double ans = oo;
        for(i = 0; i < 4; i++)
            for(j = 0; j < 4; j++)
                ans = min(ans, node[CTOA(A)+i][CTOA(B)+j]);
        printf("%.1lf",ans);
    }
    return 0;
}

题解:本题我一开始并未使用数组来储存每个城市的机场坐标。如下:

struct node{//不要这么做!!!
    int x1,y1;//不要这么做!!!
    int x2,y2;//不要这么做!!!
    int x3,y3;//不要这么做!!!
    int x4,y4;//不要这么做!!!
    int train;//不要这么做!!!
}city[110];//不要这么做!!!

导致后面的程序冗长、复杂,然后。。。我就不想写了。。。所以我copy了iwtwiioi_2 的代码,在这里表示感谢!
注意:一定要使用数组来储存机场的坐标!就像iwtwiioi_2 这样:

struct city{//应该这样做!!!
    int x[4], y[4];//应该这样做!!!
}ct[105];//应该这样做!!!

对于第四个点的求解,除了源代码的注释上的方法外还可以从向量的方面理解。首先也要讨论哪个点是直角点,而直角点无非是(x1,y1),(x2,y2),(x3,y3)中的一个,所以讨论三次。根据向量的点积的定义,假设有三个点A(x1,y1),B(x2,y2),C(x3,y3),若AB⊥BC,则B为直角点,坐标间关系满足(点乘): ( x1-x2 , y1-y2 ) • ( x3-x2 , y3-y2 ) =0 => (x1-x2) * (x3-x2) + (y1-y2) * (y3-y2)=0 。由此(x4,y4)点的坐标也可以轻松给出:x4=x1+x3-2 * x2 , y4=y1+y3-2 * y2。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值