日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

HDU 6071 Lazy Running (最短路)

發布時間:2025/3/15 编程问答 21 豆豆
生活随笔 收集整理的這篇文章主要介紹了 HDU 6071 Lazy Running (最短路) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

題目鏈接

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 (最短路)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。