hdu_1245 spfa+标记

建图O(n2),spfa O(2e)~~ok ac! so easy~

#include<iostream>
#include<iomanip>
#include<vector>
#include<string>
#include<algorithm>
#include<cmath>
#include<queue>
using namespace std;
const int maxn=111;
const int e=50;
const double oo=10e9;
const double eps=1e-8;
const int inf=0x7fffffff;
struct zz
{
    int x;
    int y;
}z[maxn];
struct z2
{
    double len;
    int from;
    int to;
}t2;
int tx,ty,n,d,now,temp,minstep;
int step[maxn];
bool can[maxn];
bool vis[maxn];
double go[maxn];
double way[maxn];
vector<z2>v[maxn];
double td,dd,minway,tmin;
queue<int>q;
void init()
{
    for(int i=0;i<=n;i++)
    {
        v[i].clear();
    }
    memset(can,false,sizeof(can));
    memset(step,0,sizeof(step));
    for(int i=1;i<=n;i++)
    {
        way[i]=oo;
    }
    way[0]=0;
    return ;
}
bool get(int a)
{
    if(abs(z[a].x-100) <= d || abs(z[a].x) <= d || abs(z[a].y) <= d || abs(z[a].y-100) <= d )
    {
        go[a]=min( min( abs(z[a].x-100) , abs(z[a].x) ) , min( abs(z[a].y) , abs(z[a].y-100) ) );
        return true;
    }
    else
    {
        return false;
    }
}
bool yes(int a,int b,double cmp=d)
{
    td=sqrt(double( (z[b].y-z[a].y)*(z[b].y-z[a].y) + (z[b].x-z[a].x)*(z[b].x-z[a].x) ) );
    if( td - eps < cmp)
    {
        t2.len=td;
        return true;
    }
    else
    {
        return false;
    }
}
void build()
{
    for(int i=1;i<=n;i++)
    {
        if( yes ( 0, i, d+7.5) )
        {
            t2.from=0;
            t2.to=i;
            v[0].push_back(t2);
        }
        if(get(i))
        {
            can[i]=true;
        }
    }
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
        {
            if(j==i)
            {
                continue;
            }
            if( yes( i, j) )
            {
                t2.from=i;
                t2.to=j;
                v[i].push_back(t2);
            }
        }
    }
    return ;
}
void spfa()
{
    memset(vis,false,sizeof(vis));
    while(!q.empty())
    {
        q.pop();
    }
    step[0]=0;
    q.push(0);
    vis[0]=true;
    while(!q.empty())
    {
        now=q.front();
        q.pop();
        for(int i=0;i<v[now].size();i++)
        {
            dd = way[now] + v[now][i].len;
            temp = v[now][i].to;
            if( dd == way[temp] )
            {
                if( step[temp] > step[now] + 1 )
                {
                    step[temp] = step[now] + 1;
                    if(!vis[temp])
                    {
                        q.push(temp);
                        vis[temp]=true;
                    }
                    continue;
                }
            }
            else if( dd < way[temp] )
            {
                way[temp] = dd;
                step[temp] = step[now] + 1;
                if(!vis[temp])
                {
                    q.push(temp);
                    vis[temp]=true;
                }
                continue;
            }
        }
        vis[now]=false;
    }
    return ;
}
bool judge()
{
    bool re=false;
    for(int i=1;i<=n;i++)
    {
        if(!can[i])
        {
            continue;
        }
        else
        {
            if(way[i]!=oo)
            {
                way[i]+=go[i];
                re=true;
            }
            else
            {
                can[i]=false;
            }
        }
    }
    if(!re)
    {
        return false;
    }
    minway=oo;
    minstep=inf;
    for(int i=1;i<=n;i++)
    {
        if(!can[i])
        {
            continue;
        }
        if(way[i]==minway)
        {
            if(step[i]<minstep)
            {
                minstep=step[i];
            }
        }
        else if(way[i]<minway)
        {
            minway=way[i];
            minstep=step[i];
        }
    }
    minway-=7.5;
    minstep++;
    return true;
}
int main()
{
    z[0].x=50;
    z[0].y=50;
    cout.setf(ios::fixed);
    while(cin>>n>>d)
    {
        init();
        for(int i=1;i<=n;i++)
        {
            cin>>z[i].x>>z[i].y;
            z[i].x+=e;
            z[i].y+=e;
        }
        build();
        spfa();
        if(judge())
        {
            cout<<setprecision(2)<<minway<<" "<<minstep<<endl;
        }
        else
        {
            cout<<"can't be saved"<<endl;
        }
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值