hdu6071-最短路&思维&多校4&同余-Lazy Running

http://acm.hdu.edu.cn/showproblem.php?pid=6071
给定四个点,构成一个矩形,和他们四个点两点之间的距离。
问你从2出发,再回到2,长度大于k的最短路。。
思路:
如果从2到达某点,再回到2不到,可以移动若干个2*m(m为2和临近点的距离)。个,来得到大于k的条件。
用dij算出到达i点并且mod 2*m为j的点。(这个最短路会一直执行,直到把这个表填完。)
然后对能回到2的方案,求最小值
(如果大于k,直接算,如果小于,就加2*m).

#include<bits/stdc++.h>
#define ll long long
using namespace std;

const int maxn=1e5;
//typedef long long ll;
typedef pair<int,ll>pii;
int t;
struct Edge{int to;ll cos;
    Edge(){};
    Edge(int _a,ll _b){to=_a,cos=_b;};

};
vector<pii>G[6];
const long long inf=2e18;
ll dp[6][maxn];
ll all;
inline void dij()
{
    priority_queue<pii,vector<pii>,greater<pii> > q;
    for(int i=0;i<=4;i++)
        for(int j=0;j<=all;j++)
            dp[i][j]=2e18;
        //cout<<m<<endl;
    q.push(make_pair(0LL,2));                           //d[s][0]不能赋值为0
    while (!q.empty())
    {
       ll w=q.top().first;
        int j=q.top().second;
        q.pop();
        if (w>dp[j][w%all]) continue;
        for(int k=0;k<G[j].size();k++)
        {
            int y=G[j][k].first;
            ll dist=w+G[j][k].second;
            if (dp[y][dist%all]>dist)                   //更新的时候更新取模后对应的点
            {
                dp[y][dist%all]=dist;
                q.push(make_pair(dist,y));
            }
        }
    }
}
ll k;
ll a1,b1,c1,d1;
int main()
{
scanf("%d",&t);
    while(t--){
         //
         for(int i=0;i<5;i++){
               G[i].clear();
          }
          //memset(G,0,sizeof(G));
          scanf("%lld%lld%lld%lld%lld",&k,&a1,&b1,&c1,&d1);
          G[1].push_back(make_pair(2,a1));
          G[2].push_back(make_pair(1,a1));
          G[2].push_back(make_pair(3,b1));
          G[3].push_back(make_pair(2,b1));
          G[3].push_back(make_pair(4,c1));
          G[4].push_back(make_pair(3,c1));
          G[4].push_back(make_pair(1,d1));
          G[1].push_back(make_pair(4,d1));
          all=min(b1,a1)*2;
          ll ans=2e18;
          dij();
         // for(int i=0;i<=100;i++)
            //cout<<dp[2][i]<<endl;
          //cout<<dp[2][165]<<endl;
          for(int i=0;i<all;i++){
               ll sum=k-dp[2][i];
               if(sum<=0)
                   ans=min(ans,dp[2][i]);
               else
                   ans=min(ans,dp[2][i]+(sum/all)*all+(sum%all>0)*all);
          }
          printf("%lld\n",ans);

    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值