[HDU6071] Lazy Running

xiaoxiao2021-02-28  116

Problem Link

Description

    给定 K d1,2 d2,3 d3,4 d4,1 du,v 表示 u v的距离),每次可以从 i 跑到i1 i+1 ,并且起点和终点只能 2 ,每个点可以经过任意次。要求在四个点之间一直跑,直到跑过的路程大于或等于K。求满足条件的最小路程。

Solution

    我们令 w=2min(d1,2,d2,3) ,即从2出发再返回2的最短路径。 然后我们开始跑最短路,定义 dis[i][j] 表示到达 i 点,路程模w等于 j 时的最短路程(有同学可能要问,为什么要模w呢?我在这里给出解释: 当到达2时,倘若 dis<K ,那么我们可以再走 Kdis+w1w w ,来使得总路程大于等于K,不妨令 k=Kdis+w1w ,则最终结果为 dis+kw ,因此对于所有模 w 相等的dis,他们对应的最终结果都相同,只是加几个w的问题)。假如跑到的最短路已经大于等于 K ,那么可以直接更新答案了。

Code

#include<queue> #include<stdio.h> #include<string.h> #include<algorithm> #include<iostream> #define M 60005 #define ll long long using namespace std; template <class T> inline void Rd(T &res){ char c;res=0;int k=1; while(c=getchar(),c<48&&c!='-'); if(c=='-'){k=-1;c='0';} do{ res=(res<<3) (res<<1) (c^48); }while(c=getchar(),c>=48); res*=k; } template <class T> inline void Pt(T res){ if(res<0){ putchar('-'); res=-res; } if(res>=10)Pt(res/10); putchar(res%10 48); } struct node{ int v; ll dis; bool operator <(const node &tmp)const{ return dis>tmp.dis; } }G[4][2]; int T; ll k,ans,dis[4][M]; int w,d[4]; int u[]={-1,1}; void calc(int x){ ans=min(ans,(k-x w-1)/w*w x); } void Dijkstra(){ priority_queue<node>que; dis[1][0]=0; que.push((node){1,0}); while(!que.empty()){ node q=que.top();que.pop(); int u=q.v; ll d=q.dis; if(dis[u][d%w]!=d)continue; for(int i=0;i<2;i ){ node nxt=G[u][i]; nxt.dis =d; ll tmp=dis[nxt.v][nxt.dis%w]; if(tmp==-1||tmp>nxt.dis){ dis[nxt.v][nxt.dis%w]=nxt.dis; if(nxt.dis>=k){ if(nxt.v==1)ans=min(ans,nxt.dis); continue; } if(nxt.v==1)calc(nxt.dis%w); que.push(nxt); } } } } int main(){ Rd(T); while(T--){ memset(dis,-1,sizeof(dis)); Rd(k); for(int i=0;i<4;i )Rd(d[i]); w=min(d[0],d[1])<<1; ans=(k w-1)/w*w; for(int i=0;i<4;i ) for(int j=0;j<2;j ){ int t=(i u[j])%4; if(t<0)t =4; if(j)G[i][j]=(node){t,d[i]}; else G[i][j]=(node){t,d[t]}; } Dijkstra(); Pt(ans); putchar('\n'); } return 0; }

    这题用了同余的思想,就是对于同余的dis他们的最终结果一定都相同。

转载请注明原文地址: https://www.6miu.com/read-25487.html

最新回复(0)