HDU6071-最短路

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

  四个点围成一个环,相邻两点之间存在路径,问从2号点出发最后再次回到二号点,在路程大于等于K的情况下的最小路程量。

我们令m=min(d1,d2)*2,可以想做是回到2号点之后再重复的走若干个m后的路程。(当然m也可以是max(d1,d2)*2,因为只要和2相邻即可)。

f[i][j]表示从2出发达到i之后,走过路程f[i][j]%m=j的最小路程,跑一遍dij,最后统计结果如果不足k就加上m补足。

 

  这样之所以是正确的在于考虑了所有的情况,对于同一个模m剩余系里面的路程他们之间的差值一定是m的倍数,所以选出一个最小的如果不足k用m补足

相当于还原到另一个路程上了,也能找到最优解。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<vector>
 4 #include<queue>
 5 #include<cmath>
 6 #include<cstring>
 7 #include<bits/stdc++.h>
 8 #define LL long long
 9 using namespace std;
10 #define LL long long
11 struct Edge
12 {
13     LL u,w;
14 };
15 struct node
16 {
17     LL u,w;
18     bool operator<(const node&chs)const{
19         return w>chs.w;
20     }
21 };
22 LL f[4][60010];
23 vector<Edge> g[4];
24 void dij(LL m)
25 {
26     memset(f,-1,sizeof(f));
27     f[1][0]=0;
28     priority_queue<node>q;
29     q.push(node{1,0});
30     while(!q.empty()){
31         int u=q.top().u,
32             w=q.top().w;
33         q.pop();
34         for(int i=0;i<g[u].size();++i){
35             if(w+g[u][i].w<f[g[u][i].u][(w+g[u][i].w)%m]||f[g[u][i].u][(w+g[u][i].w)%m]==-1){
36                 f[g[u][i].u][(w+g[u][i].w)%m]=w+g[u][i].w;
37                 q.push(node{g[u][i].u,f[g[u][i].u][(w+g[u][i].w)%m]});
38             }
39         }
40     }
41 }
42 int main()
43 {
44     LL n,m,i,j,k,d[4],t;
45     cin>>t;
46     while(t--){
47         cin>>k;
48         for(i=0;i<4;++i)cin>>d[i],g[i].clear();
49         g[0].push_back(Edge{1,d[0]});
50         g[0].push_back(Edge{3,d[3]});
51 
52         g[1].push_back(Edge{0,d[0]});
53         g[1].push_back(Edge{2,d[1]});
54 
55         g[2].push_back(Edge{1,d[1]});
56         g[2].push_back(Edge{3,d[2]});
57 
58         g[3].push_back(Edge{0,d[3]});
59         g[3].push_back(Edge{2,d[2]});
60 
61         m=min(d[0],d[1])*2;
62         dij(m);
63         LL ans=1e18;
64         for(i=0;i<m;++i){
65             if(f[1][i]==-1) continue;
66             if(f[1][i]>=k) ans=min(ans,f[1][i]);
67             else{
68 
69                 ans=min(ans,f[1][i]+
70                         (k-f[1][i])/m*m+((k-f[1][i])%m>0)*m);
71             }
72         }
73         cout<<ans<<endl;
74     }
75     return 0;
76 }

 

转载于:https://www.cnblogs.com/zzqc/p/8610766.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值