http://acm.hdu.edu.cn/showproblem.php?pid=6071
题意:
1、2、3、4四个点依次形成一个环,现在有个人从2结点出发,每次可以往它相邻的两个结点跑,求最后回到2结点并且不少于K的最短距离。
思路:
官方题解:
最后的答案可以表示为:$ans=p*(2w)+m$,这样一来,m的取值范围就是$(0<=m<2w)$,而因为m的不同,p值也会有所不同。所以我们用 d [ i ] [ m ]表示从起点出发,最后到达 i 点,距离对2w取模为m时的最小距离,这个计算一下最短路即可。
最后只需要枚举m,如果此时d [ 2 ] [ m ]不足K的话,那么就再加上2w补足即可,在所有的m中取最小值。
1 #include<iostream> 2 #include<algorithm> 3 #include<cstring> 4 #include<cstdio> 5 #include<sstream> 6 #include<vector> 7 #include<stack> 8 #include<queue> 9 #include<cmath> 10 #include<map> 11 #include<set> 12 using namespace std; 13 typedef long long ll; 14 typedef pair<int,ll> pll; 15 const ll INF = 2000000000000000000000; 16 const int maxn=1e6+5; 17 18 ll k; 19 ll m; 20 ll d[5]; 21 ll dis[5][maxn]; 22 vector<pll> G[5]; 23 24 struct HeapNode 25 { 26 int u; ll w; 27 HeapNode(int x, ll y) :u(x), w(y){} 28 bool operator <(const HeapNode& rhs) const{ 29 return w>rhs.w; 30 } 31 }; 32 33 void dijkstra() 34 { 35 priority_queue<HeapNode> Q; 36 for(int i=0;i<4;i++) 37 for(int j=0;j<=m;j++) dis[i][j]=INF; 38 39 Q.push(HeapNode(1,0)); 40 while(!Q.empty()) 41 { 42 HeapNode p=Q.top(); Q.pop(); 43 int u=p.u; 44 ll w=p.w; 45 46 for(int i=0;i<G[u].size();i++) 47 { 48 int v=G[u][i].first; 49 ll new_w=G[u][i].second+w; 50 if(dis[v][new_w%m]>new_w) 51 { 52 dis[v][new_w%m]=new_w; 53 Q.push(HeapNode(v,new_w)); 54 } 55 } 56 } 57 } 58 59 int main() 60 { 61 //freopen("in.txt","r",stdin); 62 int T; 63 scanf("%d",&T); 64 while(T--) 65 { 66 scanf("%lld",&k); 67 for(int i=0;i<4;i++) G[i].clear(); 68 for(int i=0;i<4;i++) 69 { 70 scanf("%lld",&d[i]); 71 G[i].push_back(make_pair((i+1)%4,d[i])); 72 G[(i+1)%4].push_back(make_pair(i,d[i])); 73 } 74 m=2*min(d[0],d[1]); 75 dijkstra(); 76 77 ll ans=INF; 78 for(int i=0;i<m;i++) 79 { 80 ll tmp=k-dis[1][i]; 81 if (tmp<=0) ans=min(ans,dis[1][i]); 82 else ans=min(ans,dis[1][i]+(ll)ceil((long double)tmp/m)*m); 83 } 84 printf("%lld ",ans); 85 } 86 return 0; 87 }