noip2012-開車旅行(倍增)

60分:

裸的暴力,直接搞dfs。注意double。

直接上代碼:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>

using namespace std;
const int maxn=100005;
const double INF=0x3f3f3f3f;
struct node
{
    int d1,d2;
}e,res[maxn];
int h[maxn],vis[maxn],x0,n,cnt=0;
node find(int x,int flag,node tmp)//flag==1:a
{
    int m1=INF,v1=0,m2=INF,v2=0;
    for(int i=x+1;i<=n;i++)
    {
        int temp=abs(h[x]-h[i]);
        if(temp<m1||(temp==m1&&h[i]<h[v1]))
        {m2=m1;v2=v1;v1=i;m1=temp;}
        else if(temp<m2||(temp==m2&&h[i]<h[v2]))
        {v2=i;m2=temp;}
    }
    if(flag==1) 
    {
        if(v2==0) return tmp;
        tmp.d1+=m2;
        
        if(tmp.d1+tmp.d2>x0) {tmp.d1-=m2;return tmp;} 
        else return find(v2,2,tmp);
    }
    if(flag==2)
    {
        if(v1==0) return tmp;
        tmp.d2+=m1;
        if(tmp.d1+tmp.d2>x0) {tmp.d2-=m1;return tmp;} 
        else return find(v1,1,tmp);
    }
}
int main()
{
    h[0]=INF;
    scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%d",&h[i]);
    scanf("%d",&x0);e.d1=e.d2=0;double minv=INF+1;int v=n+1;h[v]=-1;
    for(int i=1;i<=n;i++)
    {
        node x=find(i,1,e);
        double ians;
        if(x.d2==0) ians=INF;
        else ians=(x.d1*1.0)/(x.d2*1.0);
    //	cout<<x.d1<<" "<<x.d2<<endl;
    //	cout<<ians<<endl;
        if(ians<minv||(ians==minv&&h[i]>h[v])) 
        {minv=ians;v=i;}
    }
    printf("%d\n",v);
    int m;scanf("%d",&m);
    for(int i=1;i<=m;i++)
    {
        int st;scanf("%d%d",&st,&x0);
        node x=find(st,1,e);
        printf("%d %d\n",x.d1,x.d2);
    }
    return 0;
}

因爲我是一條有追求的鹹魚,所以我開始研究100分的算法惹

因爲我們要找對於每一個點的最近點和次近點。na:最近點。nb:次近點。

這裏用鏈表,不想多說惹。。。

然後我們需要知道a(b)走了多少輪後的距離,同時也要把到達的點記錄一下,考慮倍增。

fa[i][j]記得是A走2^j輪之後的距離。(B一樣)

f[i][j]記得是從i走2^j個兩步之後到達的點

然後就是求詢問啦,不想囉嗦惹,就是正常的倍增處理呀(不過要分別弄一下a,b emmm)

搞到a,b下面就很好求了啊,還是那句話!!!注意double吶

沒惹。。。代碼太醜不想貼。。。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章