题目链接

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

题解

又是一道虐信心的智商题。。。

首先有一个辅助问题,这道题转化了一波之后就会化成这个问题: 给定\(a_1,a_2,...,a_n\)和\(K\),求使得\(\sum^{n}_{i=1}a_ix_i=B\)有正整数解且\(B\ge K\)的最小\(B\)值。在本题中\(n=4, a_i\le 30000, K\le 10^{18}\).
这好像是个最短路经典问题,但是我想了三小时根本没想到做法……
大概是随便找一个\(a_k\)(一般来说找最小值节省常数)然后对于模\(a_k\)剩余系下每个数建一个点,每个数\(t\)向\((t+a_i)\mod a_k (k=1,2,...,n)\)连边,这样从\(1\)到\(j\)的最短路就是模\(a_k\)余\(j\)的最小\(B\). 这样就可以在\(O(na_i\log n)\)的时间内解决上述问题。
下面我们把这个问题\(\{ a_i\} =\{ d_i\},K=x\)的答案记作\(f(x)\).

然后考虑原问题如何转化为上述问题,我和题解的转化方式不同。
下面是我的方法(我觉得没啥问题,但是这题数据确实挺弱,有问题欢迎提出啊):
设\(d_1,d_2,d_3,d_4\)分别是\(1,2,3,4\)连向编号下一个的点的边权,我们可以将从\(2\)点出发回到\(2\)点的路径分为五种:

(1) 从\(2\)到\(1\)再回来,长度\(2d_1\).

(2) 从\(2\)到\(3\)再回来,长度\(2d_2\).

(3) 从\(2\)到\(3\)再到\(4\), 到\(1\)或者不到\(1\), 再回来。
此时\(d_2\)边恰好经过往返各一次,\(d_3\)边往返至少一次(防止出现不经过\(d_3\)直接去\(d_4\)的不合法情况),\(d_4\)边往返次数任意,长度\(2d_2+2d_3+2k_3d_3+2k_4d_4\) (\(k_3,k_4\)为任意非负整数)

(4) 从\(2\)到\(1\)再到\(4\), 到\(3\)或者不到\(3\), 再回来。与上一种情况对称,长度\(2d_1+2d_4+2k_3d_3+2k_4d_4\) (\(k_3,k_4\)为非负整数)

(5) 走一个环,环上的边可以额外往返任意多次。长度\(d_1+d_2+d_3+d_4+k_1d_1+k_2d_2+k_3d_3+k_4d_4\) (\(k_1,k_2,k_3,k_4\)为非负整数)
现在考虑简化以上讨论:(3)和(4)各做一次与做两次(5)等价,(5)做多于一次与做一次等价(因为做多次就相当于给\(k\)增加值),因此可以认为(5)至多做一次。
如果(1)(5), (2)(5)同时做都没有意义,(1)(3), (2)(4)同时做相当于做了(5)也没有意义。
考虑最优策略:

(1) 如果(5)做一次,那么(3)和(4)都没有必要做了,因为(3)和(4)的操作就相当于给(5)中的\(k\)增加值。于是这一部分的答案就是\(f(n-d_1-d_2-d_3-d_4)+d_1+d_2+d_3+d_4\).

(2) 如果(5)不做,那么(3)和(4)中可以做一个,这一部分的答案是\(\min(f(n-2d_1-2d_4)+2d_1+2d_4,f(n-2d_2-2d_3)+2d_2+2d_3)\).

(3) 如果(3)(4)(5)都不做,那么考虑(1)和(2),这一部分应该是等于上述问题\(n=2, a_1=d_1,a_2=d_2,K=n\)时的答案。
时间复杂度\(O(d\log d)\), 详细一点大概是\(ShortestPath(d,4d)+ShortestPath(d,2d)\).
这个样写可能唯一的好处就是常数比较小吧……

下面是题解的做法:
把剩余系的模数设为\(\min(d_1,d_2)\), 然后设\(f[i][j]\)表示在\(i\)这个点余数是\(j\)的答案,然后类似最短路转移DP的方法来求。
时间复杂度\(O(d\log d)\), 详细一点大概是\(ShortestPath(4d,8d)\).

代码

#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<queue>
#include<cstring>
#define llong long long
using namespace std;void read(int &x)
{int f=1;x=0;char s=getchar();while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();}x*=f;
}const int N = 6e4;
const int M = 1.2e5;
const llong INF = 1000000000000200000ll;
struct Edge
{int v,nxt; llong w;
} e[(M<<1)+3];
int fe[N+3];
struct DijNode
{int u; llong x;DijNode() {}DijNode(int _u,llong _x) {u = _u,x = _x;}bool operator <(const DijNode &arg) const {return x>arg.x;}
};
priority_queue<DijNode> pq;
llong dis[N+3];
bool vis[N+3];
llong d[5],x;
int n,en;void addedge(int u,int v,llong w)
{en++; e[en].v = v; e[en].w = w;e[en].nxt = fe[u]; fe[u] = en;
}void Dijkstra()
{memset(dis,30,sizeof(dis)); memset(vis,0,sizeof(vis));dis[0] = 0ll; pq.push(DijNode(0,0ll));while(!pq.empty()){DijNode tmp = pq.top(); pq.pop(); int u = tmp.u;if(tmp.x!=dis[u]) continue;if(vis[u]) continue;vis[u] = true;for(int i=fe[u]; i; i=e[i].nxt){int v = e[i].v;if(dis[v]>dis[u]+e[i].w && vis[v]==false){dis[v] = dis[u]+e[i].w;pq.push(DijNode(v,dis[v]));}}}
}void clear()
{for(int i=0; i<=en; i++) e[i].v = e[i].w = e[i].nxt = 0;for(int i=0; i<=n; i++) fe[i] = 0;en = n = 0;
}llong solve(llong x)
{if(x<0) return 0ll;llong ret = x;while(dis[ret%n]>ret) ret++;return ret;
}int main()
{int T; scanf("%d",&T);while(T--){scanf("%lld%lld%lld%lld%lld",&x,&d[1],&d[2],&d[3],&d[4]);llong ans = INF,tmp;n = min(min(d[1]+d[1],d[2]+d[2]),min(d[3]+d[3],d[4]+d[4]));for(int i=0; i<n; i++){for(int j=1; j<=4; j++){addedge(i,(i+d[j]+d[j])%n,d[j]+d[j]);}}Dijkstra();tmp = solve(x-d[1]-d[2]-d[3]-d[4])+d[1]+d[2]+d[3]+d[4]; ans = min(ans,tmp);tmp = solve(x-d[1]-d[1]-d[4]-d[4])+d[1]+d[1]+d[4]+d[4]; ans = min(ans,tmp);tmp = solve(x-d[2]-d[2]-d[3]-d[3])+d[2]+d[2]+d[3]+d[3]; ans = min(ans,tmp);clear();n = min(d[1]+d[1],d[2]+d[2]);for(int i=0; i<n; i++){for(int j=1; j<=2; j++){addedge(i,(i+d[j]+d[j])%n,d[j]+d[j]);}}Dijkstra();tmp = solve(x); ans = min(ans,tmp);clear();printf("%lld\n",ans);}return 0;
}

HDU 6071 Lazy Running (最短路)相关推荐

  1. HDU 6071 Lazy Running

    链接HDU 6071 Lazy Running 给出四个点1,2,3,4,1和2,2和3,3和4,4和1之间有路相连,现在从2点出发,最后回到2点,要求路径大于等于\(K\),问路径长度最短是多少,\ ...

  2. HDU 6071 Lazy Running(同余最短路的应用)

    Lazy Running 思路 还是利用同余的思想,假设存在一条长度为kkk的路,那么也一定存在一条k+basek + basek+base的路base=2∗min(d1,d2)base = 2 * ...

  3. HDU - 6071 Lazy Running 同余最短路 + 分层

    传送门 题意: 给定四个点构成一个环,给出四个点之间的距离,让后从222号点出发,最终回到222号点,求经过的距离>=k>=k>=k的最小距离. 思路: 由于从222开始,最终在22 ...

  4. hdu 5521 Meeting(最短路)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5521 题意:有1-n共n个点,给出m个块(完全图),并知道块内各点之间互相到达花费时间均为ti.已知两 ...

  5. hdu 6026 Deleting Edges(最短路计数)

    题目链接:hdu 6026 Deleting Edges 题意: 给你n个点,和一个邻接矩阵,非0表示有边,0表示没边. 现在让你删一些边,构成一棵树,使得每个点到0这个点的距离为没删边之前的最短路. ...

  6. HDU 3339 In Action 最短路+01背包

    题目链接: 题目 In Action Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) ...

  7. HDU Victor and World (最短路+状态压缩)

    题目链接:传送门 题意: n个城市m条路.刚開始在点1,求把每一个城市都遍历一边最后回到1的花费的最小值. 分析: 我们首先须要预处理出随意两个国家之间的最短距离.由于数据范围非常小,所以直接用Flo ...

  8. hdu - 2851 Lode Runner (最短路)

    http://acm.hdu.edu.cn/showproblem.php?pid=2851 首先有n层,每层的路径都有一个起点和终点和对应的危险值,如果某两层之间有交集,就能从这一层上到另外一层,不 ...

  9. 【ICPC-292】hdu 2066 一个人的旅行

    点击打开链接hdu 2066 思路:最短路+Dijkstra 分析:题目给定的起点有s个,终点有d个.要求找到从起点到这些终点最短的路径.很显然只要枚举起点然后比较最后得到最小的值. 代码: #inc ...

最新文章

  1. 64位linux下玩32位汇编编程
  2. easyui 动态设置单元格控件_插入控件-gt;引用变量-gt;实现动态图表纵横筛选
  3. 中断(interrupted()、isInterrupted())、Executor的中断
  4. 安装archlinux_archlinux/manjaro 上安装percona-server
  5. 每天一道LeetCode-----找到1,2,...,n这n个数所有的组合,每个组合有k个元素,且元素大小递增
  6. 6.2.2 二叉树的创建
  7. android studio配置java_android studio配置Javah 和ndk-build
  8. sortable 拖拽时互换目标的位置_双端通用型JS拖拽插件的封装与应用
  9. 把握不好数组边界的危害(记洛谷P1789题RE+WA的经历,Java语言描述)
  10. The table(CF-226D)
  11. php 改变图片的宽高,php缩放图片(根据宽高的等比例缩放)示例
  12. 探秘亚马逊最特别的机器人工厂:800只机器人在奔跑,人类却没有被淘汰?
  13. android excel布局,Androidui布局控件(2)表格布局excelPanel
  14. JEP 尝鲜系列 3 - 使用虚线程进行同步网络 IO 的不阻塞原理
  15. Tableau数据可视化案例
  16. 论Web App、Hybrid App、Native App三类主流APP设计差异
  17. 苹果cms主动推送php,苹果cmsv10百度主动URL推送教程
  18. ul阻燃标准有几个等级_UL阻燃等级说明
  19. 基于VirtualBox虚拟机安装Ubuntu图文教程
  20. 三维图形几何变换与投影变换

热门文章

  1. java冒泡排序找最大的值_(13)數組操作:遍歷、輸出最大值、冒泡排序、選擇排序,java已有的排序方法、折半查找...
  2. axios 登录后设置header_axios如何利用promise无痛刷新token
  3. php万年历月份处理_php实现万年历的完整代码
  4. [骨科手术导航]2D/3D医学图像配准研究_罗博博_南方科技大学
  5. C#计算两点间的距离
  6. C++中为什么没有try finally的理解
  7. python爬取时怎么获取头部header
  8. LIVE555再学习 -- 初识
  9. C语言再学习 -- 关键字void
  10. linux mount挂载设备(u盘,光盘,iso等 )使用说明