大致題意:給一張有向圖(存在自環),每條邊權均為1,現在有一人要從1號結點走到n號結點,但是這個人有乙個神奇的瞬移機器,這個機器走2
k2^k
2k(k
kk為自然數)花費的時間都為1,問從起點到終點的最小花費時間。
思路如下:
step 1.我們可以處理出所有的從乙個點到達另乙個點的距離可以為2
k2^k
2k的路徑,並把這兩個點之間連一條權值為1的邊。
step 2.在我們新得到的圖上執行最短路演算法,求出從起點到達終點花費的最少時間。
下面我們來看看如何處理step 1:
狀態表示:用f[i
][j]
[k
]f[i][j][k]
f[i][j
][k]
記錄能否通過2
k2^k
2k的距離從i
ii到達jjj.
轉移方程:if(
f[i]
[u][
k−1]
if(f[i][u][k-1]
if(f[i
][u]
[k−1
]&&f[u
][j]
[k−1
])
f[u][j][k-1])
f[u][j
][k−
1]) 則f[i
][j]
[k
]f[i][j][k]
f[i][j
][k]
為真。需要注意:因為題意已經給出任意邊的邊權均為1,則可以用反證法證明:若f[i
][j]
[k
]f[i][j][k]
f[i][j
][k]
為真,則一定存在中間結點使得f[i
][u]
[k−1
]f[i][u][k-1]
f[i][u
][k−
1]&&f [u
][j]
[k−1
]f[u][j][k-1]
f[u][j
][k−
1]為真。
**如下:
#include
#include
using
namespace std;
const
int n =
100, m =
20000
;const
int k =35;
int f[n]
[n][k]
;int g[n]
[n];
int n,m;
intmain()
for(
int u=
1;u<=32;
++u)
for(
int k=
1;k<=n;
++k)
for(
int i=
1;i<=n;
++i)
for(
int j=
1;j<=n;
++j)
if(f[i]
[k][u-1]
==1&&f[k]
[j][u-1]
==1)for
(int k=
1;k<=n;
++k)
for(
int i=
1;i<=n;
++i)
for(
int j=
1;j<=n;
++j)
g[i]
[j]=
min(g[i]
[k]+g[k]
[j],g[i]
[j]);
cout<[n]
}
洛谷 P1613 跑路
題目描述 小a的工作不僅繁瑣,更有苛刻的規定,要求小a每天早上在6 00之前到達公司,否則這個月工資清零。可是小a偏偏又有賴床的壞毛病。於是為了保住自己的工資,小a買了乙個十分牛b的空間跑路器,每秒鐘可以跑2 k千公尺 k是任意自然數 當然,這個機器是用longint存的,所以總跑路長度不能超過ma...
跑路 洛谷p1613
小a的工作不僅繁瑣,更有苛刻的規定,要求小a每天早上在6 00之前到達公司,否則這個月工資清零。可是小a偏偏又有賴床的壞毛病。於是為了保住自己的工資,小a買了乙個十分牛b的空間跑路器,每秒鐘可以跑2 k千公尺 k是任意自然數 當然,這個機器是用longint存的,所以總跑路長度不能超過maxlong...
洛谷P1613 跑路
題目 倍增直接用圖論演算法必然解決不了這個問題,所以可以使用倍增演算法優化。我們遇到這個題該怎麼想,首先,題目要求的值是1到n的最小代價。代價是路徑的二進位制中1的個數。我們先預處理出每兩點之間是否有邊權和為 1 k 的路徑。這樣的話,代價預處理就可以只需考慮1的情況,因為每個數都可以由 1 處理之...