Floyd-Warshall算法
算法簡介;
Floyd-Warshall算法(以下簡稱floyd)是求解圖中任意兩點最短路問題的算法。運用的思想是動態規劃。
狀態轉移方程 dist[i][j]=min(dist[i][j],dist[i][k]+dist[k][j])(1<=k<=n)
int n;//節點個數
void init()
{
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
dist[i][j]=INF;//初始賦值爲無窮,這裏是指很大的數,一般爲最大值的1/2 -1
}
}
}
void floyd()//注意k,i,j的順序,需細細體會
{
for(int k=1;k<=n;k++)
{
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
if(dist[i][j]>dist[i][k]+dist[k][j])
dist[i][j]=dist[i][k]+dist[k][j];
}
}
}
}
例題 HDU1596
題目中文,也很好理解。題意就不說了。設兩星球之間的安全值爲safe,則-ln(safe)爲兩點之間的路徑,則就變成了求任意兩點的最短路的問題了
代碼如下:
#include<iostream>
#include<cstdio>
#include<cmath>
#define E 2.718282
using namespace std;
const int inf=1e+9;
const int maxn=1005;
double d[maxn][maxn];
int n;
void floyd()
{
for(int k=1;k<=n;k++)
{
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
if(d[i][j]>d[i][k]+d[k][j])
d[i][j]=d[i][k]+d[k][j];
}
}
}
}
int main()
{
while(cin>>n)
{
double cost;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
scanf("%lf",&cost);
if(cost==0)
{
d[i][j]=inf;
}
else
d[i][j]=-log(cost);
}
}
floyd();
int check;
scanf("%d",&check);
int a,b;
for(int i=0;i<check;i++)
{
scanf("%d %d",&a,&b);
if(d[a][b]!=inf)
printf("%.3f\n",pow(E,-d[a][b]));
else
puts("What a pity!");
}
}
return 0;
}
你也可以不用將安全值轉換成路徑,畢竟調用log,pow函數還是會產生誤差的
代碼如下:
#include<iostream>
#include<cstdio>
#include<cmath>
#define E 2.718282
using namespace std;
const int maxn=1005;
double d[maxn][maxn];
int n;
void floyd()
{
for(int k=1;k<=n;k++)
{
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
if(d[i][j]<d[i][k]*d[k][j])
d[i][j]=d[i][k]*d[k][j];
}
}
}
}
int main()
{
while(cin>>n)
{
double cost;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
scanf("%lf",&cost);
d[i][j]=cost;
}
}
floyd();
int check;
scanf("%d",&check);
int a,b;
for(int i=0;i<check;i++)
{
scanf("%d %d",&a,&b);
if(d[a][b]!=0)
printf("%.3f\n",d[a][b]);
else
puts("What a pity!");
}
}
return 0;
}