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呐

没惹。。。代码太丑不想贴。。。

 

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