hihocoder1138涨姿势的最短路

题目的大致意思是说,给定n个点的座标,让我们求起点到终点的最短距离.

点点之间的距离是min(abs(x1-x2),abs(y1-y2))

一开始根本不会写.直到看到了博主:http://blog.csdn.net/octopusflying/article/details/51125562的代码

思路大体是,从点1到点n的最短路必然经过这个点的前驱和后继.相对的,有x方向的前驱后继,y方向的前驱后继

因此需要按照x,y排序,之后对每个点的对应的前驱后继连边,权重就参照距离算法.

然后最多有4n条边,再用spfa求解.

代码如下

#include<bits/stdc++.h>
using namespace std;
#define inf 0x3f3f3f3f3f
struct node
{
    int id;
    int st,len;
};
vector<node>v;
queue<int>q;
int n,m,x;
bool cmp(node a,node b)
{
    return a.st<b.st;
}
bool cmp2(node a,node b)
{
    return a.id<b.id;
}

int checkst(int need)
{
    int lastst=0,lastlen=0;
    int temp;
    int minkongst=inf;
    for(int i=0; i<v.size(); i++) //先看空挡够不够
    {
        //cout<<v[i].st<<endl;
        temp = v[i].st-lastst-lastlen;//空挡长度
        //cout<<"temp:"<<temp<<endl;
        if(temp>0)
        {
            minkongst = min(minkongst,lastst+lastlen);
        }
        if(temp>=need)
        {
            return lastst+lastlen;
        }
        lastst = v[i].st;
        lastlen=v[i].len;
    }
    //按时间顺序删除
    int deleteid = q.front();
    q.pop();
    vector<node>::iterator iter;
    for(iter=v.begin(); iter!=v.end(); iter++) //再从第一个开始替换
    {
        if((*iter).id==deleteid)
            v.erase(iter);
    }
    return -1;
}

int main()
{
    //freopen("1.txt","r",stdin);
    node add;
    cin>>n>>m;
    add.len=0;
    add.st=m;
    add.id=-1;
    v.push_back(add);
    for(int i=1; i<=n; i++)
    {
        q.push(i);
        cin>>x;
        add.len=x;
        add.id=i;
        add.st=checkst(x);
        while(add.st==-1){
            add.st=checkst(x);
        }
        v.push_back(add);
        sort(v.begin(),v.end(),cmp);
//        for(int j=0;j<v.size();j++)
//            cout<<v[j].st<<"-"<<v[j].id<<" " ;
//        cout<<endl;
    }

    sort(v.begin(),v.end(),cmp2);
    for(int i=0; i<v.size(); i++)
    {
        if(v[i].id==-1)continue;
        cout<<v[i].id<<" "<<v[i].st<<endl;
    }
    return 0;
}
点赞