SCOI2010 传送带 [三分/模拟退火]

题目描述

在一个2维平面上有两条传送带,每一条传送带可以看成是一条线段。两条传送带分别为线段AB和线段CD。lxhgww在AB上的移动速度为P,在CD上的移动速度为Q,在平面上的移动速度R。现在lxhgww想从A点走到D点,他想知道最少需要走多长时间

输入输出格式

输入格式:

输入数据第一行是4个整数,表示A和B的坐标,分别为Ax,Ay,Bx,By

第二行是4个整数,表示C和D的坐标,分别为Cx,Cy,Dx,Dy

第三行是3个整数,分别是P,Q,R

输出格式:

输出数据为一行,表示lxhgww从A点走到D点的最短时间,保留到小数点后2位

输入输出样例

输入样例#1:

0 0 0 100
100 0 100 100
2 2 1

输出样例#1:

136.60

说明

对于100%的数据,1<= Ax,Ay,Bx,By,Cx,Cy,Dx,Dy<=1000
1<=P,Q,R<=10

题解

这道题其实可以用模拟A掉

把平面上的线段全部看成向量,因为有了ABCD四个点的坐标,所以我们可以用坐标来表示向量,除此之外我们需要设置一个变量 * 上这个初始向量就可以得到这个向量方向上的任意一条向量,也就是用两种循环来枚举,每次变量的改变多少就需要自己调试参数了

正解还是三分法,也可以用模拟退火,以后再补

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<string>
#include<ctime>
#include<algorithm>
#define in(i) (i=read())
using namespace std;
const double dt=2e-4;
int read() {
    int ans=0,f=1; char i=getchar();
    while(i<'0' || i>'9') {if(i=='-') f=-1; i=getchar();}
    while(i>='0'&& i<='9') {ans=(ans<<1)+(ans<<3)+i-'0'; i=getchar();}
    return ans*f;
}
double ans=2147483647;
double p,r,q;
struct node {
    double x,y;
}a[10];
inline double dis(node a,node b) {
    return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
inline node get(node a,node b,double k) {
    return (node) {(b.x-a.x)*k+a.x, (b.y-a.y)*k+a.y};
}
inline double check(double i,double j) {
    node t1=get(a[1],a[2],i), t2=get(a[3],a[4],j);
    return dis(a[1],t1)/p+dis(t1,t2)/r+dis(t2,a[4])/q;;
}
int main()
{
    //freopen("walk.in","r",stdin);
    //freopen("walk.out","w",stdout);
    cin>>a[1].x>>a[1].y>>a[2].x>>a[2].y>>a[3].x>>a[3].y>>a[4].x>>a[4].y;
    cin>>p>>q>>r;
    for(double i=0;i<=1;i+=dt) {
        for(double j=0;j<=1;j+=dt) {
            ans=min(ans,check(i,j));
        }
    }
    printf("%.2lf",ans);
    return 0;
}

原文地址:https://www.cnblogs.com/real-l/p/9319364.html