zoukankan      html  css  js  c++  java
  • NOIP 2012 开车旅行

    感觉今天被这题虐的脑细胞都没了。。。题解打了一半就不想想下去了。。。

    NOIP 2012 开车旅行
    这个题目主要就是求两个问题:①求从哪个城市开始,小A和小B所开路程的比值最小。②求从给定城市出发,小A和小B各自走的路程。
    首先把城市的高度拿去排序,放到链表中。再分别找到离他最近和次近的城市,记录下来。
    再来就是倍增了
    因为它数据的原因,我们的j最多开到17就好了(这句废话)
    倍增主要书处理每个点向前走2^j步能到的城市和到这个城市A,B需要走的距离
    再来说方程吧:f[I,j]=f[f[I,j-1],j-1]];
    a[I,j]=a[I,j-1]+a[f[I,j-1],j-1];
    b[I,j]=b[I,j-1]+b[f[I,j-1],j-1]
    算出来这些,题目要求的两个问题就好解决了。
    介于语言表达问题,先来看程序。。。。。。。。。

      1 label 1;
      2 type point=^rec;
      3      rec=record
      4      z:longint;
      5      q,h:point;
      6 end;
      7 var i,n,m,t,s,top,j,k,ans,dk,lj:longint;
      8     h,a,mi,mmi,b:array[0..100000] of int64;
      9     XXX:array[0..100000] of point;
     10     fa,na,nb:array[0..100000,-2..17] of int64;
     11     p,q:point;
     12     bo:array[0..100000] of boolean;
     13     re:real;
     14     la,lb,x:int64;
     15     flag:boolean;
     16 procedure qsort(l,r:longint);
     17       var i,j,x,y:longint;
     18 begin
     19   x:=h[(l+r) div 2]; i:=l; j:=r;
     20   repeat
     21     while h[i]<x do inc(i);
     22     while x<h[j] do dec(j);
     23     if not (i>j) then
     24      begin
     25       y:=h[i]; h[i]:=h[j]; h[j]:=y;  y:=a[i]; a[i]:=a[j];  a[j]:=y;
     26       inc(i);  dec(j);
     27      end;
     28   until i>j;
     29   if l<j then sort(l,j);
     30   if i<r then sort(i,r);
     31 end;
     32 procedure deal;
     33 begin
     34   la:=0; lb:=0; k:=s; flag:=true;
     35   while flag do
     36    begin
     37     j:=0;
     38     while (x>=la+lb+na[k,j]+nb[k,j])and(fa[k,j]<>0) do inc(j);
     39     if (x<la+lb+na[k,j]+nb[k,j])and(j=0) then flag:=false;
     40     if fa[k,0]=0 then flag:=false;
     41     la:=la+na[k,j-1];
     42     lb:=lb+nb[k,j-1];
     43     k:=fa[k,j-1];
     44    end;
     45   if (mmi[k]<>0)and(la+lb+abs(b[mmi[k]]-b[k])<=x) then
     46    la:=la+abs(b[mmi[k]]-b[k]);
     47 end;
     48 begin
     49   assign(input,'drive.in'); reset(input);
     50   assign(output,'drive.out'); rewrite(output);
     51   readln(n);  //读入
     52   for i:=1 to n do
     53    begin   
     54     read(h[i]);  
     55     a[i]:=i;  //记录每个点的位置
     56     b[i]:=h[i];
     57    end;
     58   qsort(1,n);  //递增的快排
     59   new(XXX[a[1]]); 
     60   XXX[a[1]]^.q:=nil; 
     61   XXX[a[1]]^.z:=a[1]; 
     62   for i:=2 to n do
     63    begin
     64     new(XXX[a[i]]);
     65     XXX[a[i]]^.q:=XXX[a[i-1]];   //^.q表示前面一个指针
     66     XXX[a[i]]^.z:=a[i];           //^.z表示这个指针是哪个数
     67     XXX[a[i-1]]^.h:=XXX[a[i]];  // ^.h表示后面一个指针   
     68    end;
     69   XXX[a[n]]^.h:=nil;
     70   for i:=1 to n do
     71    begin
     72     p:=XXX[i]^.q;  //为了方便,把它前面的指针赋值给p
     73     q:=XXX[i]^.h;  //为了方便,把它后面的指针赋值给p 
     74     if (p=nil)and(q=nil) then goto 1; //goto 不懂可以百度
     75     if (q<>nil)and((p=nil)or(b[i]-b[p^.z]>b[q^.z]-b[i])) then  //方便找最近的
     76      begin                                                    
     77       mi[i]:=q^.z;  //记录这个点
     78       q:=q^.h;        
     79       if (p=nil)and(q=nil) then goto 1;  
     80       if (q<>nil)and((p=nil)or(b[i]-b[p^.z]>b[q^.z]-b[i])) then mmi[i]:=q^.z else mmi[i]:=p^.z;
     81      end
     82     else 
     83      begin  //方便找次近的
     84       mi[i]:=p^.z;  
     85       p:=p^.q;
     86       if (p=nil)and(q=nil) then goto 1;
     87       if (p<>nil)and((q=nil)or(b[q^.z]-b[i]>=b[i]-b[p^.z])) then
     88        mmi[i]:=p^.z else mmi[i]:=q^.z;
     89      end;
     90 1:  if XXX[i]^.q<>nil then XXX[i]^.q^.h:=XXX[i]^.h;    
     91     if XXX[i]^.h<>nil then XXX[i]^.h^.q:=XXX[i]^.q;    
     92     XXX[i]:=nil; //最后要记得把这个指针记空
     93    end;
     94   for i:=1 to n do if mmi[i]<>0 then       
     95    begin
     96     t:=mmi[i];
     97     if mi[t]<>0 then
     98      begin
     99       nb[i,0]:=abs(b[t]-b[mi[t]]);
    100       na[i,0]:=abs(b[i]-b[t]);
    101      end;
    102    fa[i,0]:=mi[t];
    103    end;
    104    for i:=1 to n do fa[i,-1]:=i;
    105    for j:=1 to 17 do
    106     for i:=1 to n do
    107      begin
    108       fa[i,j]:=fa[fa[i,j-1],j-1];
    109       if fa[i,j]<>0 then
    110        begin
    111         na[i,j]:=na[i,j-1]+na[fa[i,j-1],j-1];
    112         nb[i,j]:=nb[i,j-1]+nb[fa[i,j-1],j-1];
    113        end;
    114      end;
    115   read(x);
    116   re:=10000000000;
    117   for s:=1 to n do
    118    begin
    119     deal;
    120     if (lb<>0)and(re>la/lb) then
    121      begin
    122       re:=la/lb;
    123       ans:=s;
    124      end;
    125    end;
    126   writeln(ans);
    127   read(m);
    128   for i:=1 to m do
    129    begin
    130     read(s,x);  //依据s,x判断能走到哪个城市及A,B走过距离
    131     deal;
    132     writeln(la,' ',lb);
    133    end;
    134   close(input); close(output);
    135 end.
    View Code
  • 相关阅读:
    MySql的常用命令
    yum命令配置及使用说明和常见问题处理
    oracle12c创建用户和表空间出现的问题
    oracle云部署
    ORA-12154: TNS:could not resolve the connect identifier specified
    Linux之iptables
    Linux之MySQL
    Linux之apache
    oracle查锁表
    cookie 和 HttpSession
  • 原文地址:https://www.cnblogs.com/oxxxo/p/3374314.html
Copyright © 2011-2022 走看看