1. 程式人生 > >bzoj1857: [Scoi2010]傳送帶

bzoj1857: [Scoi2010]傳送帶

看到這題第一感覺暴力呀233

然後就亂搞水過了(資料太水?)

我的做法是將AB,CD分別等分為512段

這樣AB,CD上各有513個頂點,不妨設AB上的頂點為E,CD上的頂點為F

通過數學容易得到A到D的最短時間移動路徑是AE-EF-FD,

那列舉E在AB上那513個頂點位置,列舉F在CD上那513個頂點位置,

其中滿足AE/P+FD/Q+EF/R最小的E,F點時路徑移動時間最短,此時AE/P+FD/Q+EF/R就是答案

由於線段長度有限,取512段基本可以滿足精度問題

聽神犇說這題是三分?我表示一臉懵逼2333

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<cstdlib>
using namespace std;
int ax,ay,bx,by,cx,cy,dx,dy;
int p,q,r;
int tza=0,tzb=0;
double ka,kb,ba,bb;
double sum=0,ans=0x3f3f3f3f;
struct data{
       double xi,yi;
}op[2005],kp[2005];
int cnt=2,tot=2;
void find(double axx,double ayy,double bxx,double byy,int timm)
{
     if(timm>8)return ;
     double oxx,oyy;
     oxx=(axx+bxx)/2.0;
     oyy=(ayy+byy)/2.0;
     cnt++;
     op[cnt].xi=oxx;
     op[cnt].yi=oyy;
     find(axx,ayy,oxx,oyy,timm+1);
     find(oxx,oyy,bxx,byy,timm+1);
}
void seach(double axx,double ayy,double bxx,double byy,int timm)
{
     if(timm>8)return ;
     double oxx,oyy;
     oxx=(axx+bxx)/2.0;
     oyy=(ayy+byy)/2.0;
     tot++;
     kp[tot].xi=oxx;
     kp[tot].yi=oyy;
     seach(axx,ayy,oxx,oyy,timm+1);
     seach(oxx,oyy,bxx,byy,timm+1);
}
void lcr(int x,int y)
{
     double lena,lenb,lenc;
     lena=sqrt((kp[x].xi-ax)*(kp[x].xi-ax)+(kp[x].yi-ay)*(kp[x].yi-ay));
     lena/=(double)p;
     lenb=sqrt((op[y].xi-dx)*(op[y].xi-dx)+(op[y].yi-dy)*(op[y].yi-dy));
     lenb/=(double)q;
     lenc=sqrt((kp[x].xi-op[y].xi)*(kp[x].xi-op[y].xi)+(kp[x].yi-op[y].yi)*(kp[x].yi-op[y].yi));
     lenc/=(double)r;
     sum=(lena+lenb+lenc);
     ans=min(sum,ans);
}
int main()
{
    int i,j,k,l;
    scanf("%d%d%d%d",&ax,&ay,&bx,&by);
    scanf("%d%d%d%d",&cx,&cy,&dx,&dy);
    scanf("%d%d%d",&p,&q,&r);
    op[1].xi=cx;op[1].yi=cy;
    op[2].xi=dx;op[2].yi=dy;
    find(cx,cy,dx,dy,0);
    kp[1].xi=ax;kp[1].yi=ay;
    kp[2].xi=bx;kp[2].yi=by;
    seach(ax,ay,bx,by,0);
    for(i=1;i<=tot;i++){
        for(j=1;j<=cnt;j++){
            lcr(i,j);
            }
        }
    printf("%.2lf",ans);
    return 0;
}