开车,开车!!!

倍增问题

其实说实话,我现在也不知道倍增问题是什么东西!

题目链接:
P1081 开车旅行

标成如下:

#include<bits/stdc++.h>
#define LL long long 
#define N 100005         //小A开山蹦蹦,小B很正常 0是B 1是A 
using namespace std;
struct sd{
    int num,high;
    bool operator < (const sd njc) const
    {
        return high<njc.high;
    }
}city[N];
set<sd> s;//定义集合set方便后面排序用。 
set<sd> ::iterator it;//说白了就是一个指针 
int goal[N][2],dis[N][2];//分别定义的是N的目标点和N到目标点的距离 
int loc[N][25], f[N][25][2];//分别存的是 loc从i号点(i<=n)经过2^j的操作到达点的位置(首先存的是一轮)(从goal传入) 
 //f代表从第i个点(i<=N)经过2^j的操作到达点的距离(从dis传入)
void update(sd x,sd y)
{
    if(!goal[x.num][0])
    {
        goal[x.num][0]=y.num;
        dis[x.num][0]=abs(x.high-y.high);
    }
    else if(abs(x.high-y.high)<dis[x.num][0]||(abs(x.high-y.high)==dis[x.num][0]&&y.high<city[goal[x.num][0]].high))
    {//如果现在两个的差小于原来的差 或者 相等但是现在的海拔要低一些那么见下面操作 
        goal[x.num][1]=goal[x.num][0];
        dis[x.num][1]=dis[x.num][0];
        goal[x.num][0]=y.num;
        dis[x.num][0]=abs(x.high-y.high);
    }
    else if(abs(x.high-y.high)<dis[x.num][1]||(abs(x.high-y.high)==dis[x.num][1]&&y.high<city[goal[x.num][1]].high))
    {//important
        goal[x.num][1]=y.num;
        dis[x.num][1]=abs(x.high-y.high);
    }
    else if(!goal[x.num][1])
    {
        goal[x.num][1]=y.num;
        dis[x.num][1]=abs(x.high-y.high);
    }
}
void query(int i,int x,LL &dista,LL &distb)
{
    for(int j=20;j>=0;--j)
    {
        if(f[i][j][0]+f[i][j][1]<=x&&loc[i][j])
        {
            dista+=f[i][j][0];
            distb+=f[i][j][1];
            x-=(f[i][j][0]+f[i][j][1]);
            i=loc[i][j];
        }
    }
    if(goal[i][1]&&dis[i][1]<=x)//important 这里的1指的是A,这里在判断最后A是否还可以开车 
    {
        dista+=dis[i][1];
    }
}
int main()
{
    int n;
    cin>>n;//读入
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&city[i].high);
        city[i].num=i;
    } 
    for(int i=n;i>=1;i--)//预处理操作 
    {
        s.insert(city[i]);
        it=s.find(city[i]);
        if(it!=s.begin())
        {
            it--;
            update(city[i],*it);
            if(it!=s.begin())
            {
                it--;
                update(city[i],*it);
                it++;
            }
            it++;
        }
        if((++it)!=s.end())
        {
            update(city[i],*it);
            if((++it)!=s.end())
                update(city[i],*it);
                it--;
        }
        it--;
    }
    for(int i=1;i<=n;i++)
    {
        loc[i][0]=goal[goal[i][1]][0];//每一轮开车开完后到达的位置 (A,B算一轮) 
        f[i][0][0]=dis[i][1]; 
        f[i][0][1]=dis[goal[i][1]][0];
    }
    for(int j=1;j<=20;j++)
    {
        for(int i=1;i<=n;i++)
        {
            loc[i][j]=loc[loc[i][j-1]][j-1];
            f[i][j][0]=f[i][j-1][0]+f[loc[i][j-1]][j-1][0];
            f[i][j][1]=f[i][j-1][1]+f[loc[i][j-1]][j-1][1];
        }
    }
    int limit;//下面开始解决题目中的第一个问题!!! 
    cin>>limit;
    LL a=1e5;
    LL b=0;
    int began=0;
    for(int i=1;i<=n;i++)
    {
        LL dista=0, distb=0;
        query(i,limit,dista,distb);
        if(distb&&(distb*a>dista*b))
        {
            began=i;
            a=dista;
            b=distb;
        }
    } 
    //printf("%lld\n",began)
    cout<<began<<endl;
    int m;
    cin>>m;//下面的代码解决题目中的第二个问题 
    for(int i=1;i<=m;++i)
    {
        LL dista=0,distb=0;
        int s,x;
        scanf("%d%d",&s,&x);
        query(s,x,dista,distb);
        printf("%lld %lld\n",dista,distb);
        //cout<<dista<<' '<<distb<<endl;
    }
    return 0;
} 

程序长的我都不想写解题报告了!

后续持续更新:(2018.2.5 morning)

原文链接: https://www.cnblogs.com/mudrobot/p/13330983.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍;

也有高质量的技术群,里面有嵌入式、搜广推等BAT大佬

    开车,开车!!!

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/367823

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年3月2日 下午6:00
下一篇 2023年3月2日 下午6:00

相关推荐