HDU6071 Lazy Running

链接:http://acm.hdu.edu.cn/showproblem.php?pid=6071

挺晚了,还是决定写一下题解~~~

题意:给你四个点,组成一个圈,求从2出发再回到2的所有路径中大于K的最小值;

思路:其实跟前一篇大容量背包一样利用同余系最短路求;

可以这么理解,我对满足要求的所有路径分类,标准是模m的值为j(0=<j<m)的所有路径分到一组,而dis[i][j]表示满足从1到i模m为j的最小

路径,因为我们求的是最短路径,对于一组同余系,我记录最小的解即可,m是从1出来的两条边中最短的那条边的二倍,之所以是二倍

,因为我要满足一个环,使原来的解加上一个环依旧是一个解,最后把dis[1][0~m-1]的数都变成大于k得数,从中取最小值即可;为什么

结果一定是正解呢?因为发现在这我把所有的解变成了dis[1][0~m-1]+x*m的形式了,那我从dis[1][0~m-1]出发,一定可以找到解空间的

所有情况,那我找出来的最小值必然是正解了;

代码:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<queue>
#include<cstring>
using namespace std;
typedef long long LL;
const int maxn=6e4+10;
bool vis[5][maxn];
LL dis[5][maxn],G[5][5];
struct node
{
    int p,j;
    node(int _p,int _j):p(_p),j(_j){}
};
void spfa(int s,int m)
{
    memset(vis,0,sizeof vis);
    memset(dis,0x3f,sizeof dis);
    queue<node>q;
    q.push(node(1,0));
    dis[1][0]=0;
    vis[1][0]=true;
    while(!q.empty())
    {
        node tn=q.front();
        q.pop();
        int v=tn.p,j=tn.j;
        vis[v][j]=false;
        for(int i=-1;i<2;i+=2)
        {
            int tv=(v+i+4)%4;
            LL d=dis[v][j]+G[v][tv];
            if(dis[tv][d%m]>d)
            {
                dis[tv][d%m]=d;
                if(!vis[tv][d%m])
                {
                    q.push(node(tv,d%m));
                    vis[tv][d%m]=true;
                }
            }
        }
    }
}
int main()
{
    //freopen("input.txt","r",stdin);
    int  T;
    for(scanf("%d",&T);T;T--)
    {
        LL k;scanf("%lld",&k);
        for(int i=0;i<4;i++)
        {
            scanf("%lld",&G[i][(i+1)%4]);
            G[(i+1)%4][i]=G[i][(i+1)%4];
        }
        int m=2*min(G[1][0],G[1][2]);
        spfa(1,m);
        LL ans=((k-1)/m+1)*m;
        for(int i=0;i<m;i++)
        {
            LL tmp=dis[1][i]>k?dis[1][i]:((k-dis[1][i]-1)/m+1)*m+dis[1][i];
            ans=min(ans,tmp);
        }
        printf("%lld\n",ans);
    }
    return 0;
}
时间: 2024-08-05 22:48:37

HDU6071 Lazy Running的相关文章

hdu-6071 Lazy Running

In HDU, you have to run along the campus for 24 times, or you will fail in PE. According to the rule, you must keep your speed, and your running distance should not be less than K meters. There are 4 checkpoints in the campus, indexed as p1,p2,p3 and

【最短路】【spfa】hdu6071 Lazy Running

给你一个4个点的环,问你从2号点出发, 再回到2号点,长度>=K的最短路是多少.环上的边长度不超过30000. 跑出来所有dis(2,j)以后,然后for一遍j,根据dis(2,j)+t*2*w>=K,解出来对于每个j而言最小的t,然后尝试更新答案即可.如果dis(2,j)已经大于等于K了,那直接用其尝试更新答案. 跟CDOJ1633很像. #include<cstdio> #include<queue> #include<algorithm> #inclu

HDU 6071 Lazy Running (同余最短路)

Lazy Running Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 524288/524288 K (Java/Others)Total Submission(s): 101    Accepted Submission(s): 40 Problem Description In HDU, you have to run along the campus for 24 times, or you will fail in PE

HDU 6071 Lazy Running (同余最短路 dij)

Lazy Running Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 524288/524288 K (Java/Others)Total Submission(s): 1384    Accepted Submission(s): 597 Problem Description In HDU, you have to run along the campus for 24 times, or you will fail in

hdu 6071 Lazy Running(同余最短路)

题目链接:hdu 6071 Lazy Running 题意: 给你4个点,每两个相邻点有一个距离,现在让你在这四个点来回跑步,从2开始,最后回到2,问你找一个距离ans,ans>=k,问最小的ans是多少. 题解: Claris的官方题解: 1 #include<bits/stdc++.h> 2 #define F(i,a,b) for(int i=(a);i<=(b);++i) 3 using namespace std; 4 using ll=long long; 5 6 co

HDU 6071 Lazy Running(最短路)

[题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=6071 [题目大意] 给出四个点1,2,3,4,1和2,2和3,3和4,4和1 之间有路相连, 现在从2点出发,最后回到2点,要求路径大于等于K,问路径长度最短是多少 [题解] 取一条与2相连的权值最小的边w. 若存在一条从起点到终点的长度为k的路径, 那么必然存在一条长度为k+2w的路径,只要一开始在那条边上往返走就好了. 设dij表示从起点到i,路径长度模2w为j时,路径长度的最小值. 用最短

HDU 6071 同余最短路 spfa

Lazy Running Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 524288/524288 K (Java/Others)Total Submission(s): 657    Accepted Submission(s): 284 Problem Description In HDU, you have to run along the campus for 24 times, or you will fail in P

noip考前抱佛脚 数论小总结

exCRT 求解韩信点兵问题,常见的就是合并不同\(mod\). 先mo一发高神的板子 for(R i=2;i<=n;++i){ ll Y1,Yi,lcm=Lcm(p[i],p[1]); exgcd(p[1],p[i],a[i]-a[1],Y1,Yi); add(a[1],mul(p[1],Y1,lcm),lcm),p[1]=lcm; } 思想是合并方程组,现在假设我们要求解的是: \[x-p_0*y_0=a_0\]\[x-p_i*y_i=a_i\] \(x\)是实际的值,显然有: \[p_0*

BZOJ 3011: [Usaco2012 Dec]Running Away From the Barn( dfs序 + 主席树 )

子树操作, dfs序即可.然后计算<=L就直接在可持久化线段树上查询 ------------------------------------------------------------------- #include<bits/stdc++.h> using namespace std; #define M(l, r) (((l) + (r)) >> 1) const int maxn = 200009; typedef long long ll; inline ll