一、题目:Sightseeing trip
二、题意:给出N个旅游景点与M跳旅游路线,选择一条总路径最短且旅游景点又最多,而且是从头到尾是一条回路。
三、解决办法:
此题其实是经典的Floyd_Warshal算法。
四、源代码:
#include "stdio.h"
#include "string.h"
const int n = 101;
const int MAXINT = 123456789;
int N, M;
int d[n][n]; //i到j的最短路径
int Memory[n][n]; //记录i可以到那些旅游景点
int Initial[n][n]; //记录最初的路径
int result[n]; //记录最佳回路
int num; //记录最佳回路旅游景点的个数
int best;
void floyd()
{
int i, j, k;
int sum; //记录当前一个回路的权值
int p;
//Floyd_Warshell算法:
for (k = 0; k < N; ++k)
{
for (i = 0; i < k; ++i)
{
for (j = 0; j < k; ++j)
{
//判断i到j是否可行
if (Initial[i][k] && Initial[k][j] && j != i)
{
//记录k-i-j-k一个回路的权值
if ((sum = d[i][j] + Initial[k][i] + Initial[j][k]) < best)
{
best = sum;
num = 1;
result[0] = k; //记录第一个景点k
p = i;
while (p != -1) //一直都在记录回路的景点数目,直到没有为止
{
result[num++] = p;
p = Memory[p][j];
}
}
}
}
}
//以k为中心的话,记录i到j较小值(其中可能经过>2的旅游景点),
//同时改变Memory记录的内容
for (i = 0; i < N; ++i)
{
for (j = 0; j < N; ++j)
{
if (d[i][j] > d[i][k] + d[k][j])
{
d[i][j] = d[i][k] + d[k][j];
Memory[i][j] = Memory[i][k];
}
}
}
}
}
int main()
{
freopen("1.txt", "r", stdin);
int i, j, u, v, w;
memset(Memory, -1, sizeof(Memory));
scanf("%d %d", &N, &M);
//初始化
for (i = 0; i < N; ++i)
{
for (j = i + 1; j < N; ++j)
{
d[i][j] = d[j][i] = MAXINT;
}
d[i][i] = 0;
}
for (i = 0; i < M; ++i)
{
scanf("%d %d %d", &u, &v, &w);
u--;
v--;
if (w < d[u][v])
{
Initial[u][v] = Initial[v][u] = d[u][v] = d[v][u] = w;
}
Memory[u][v] = v; //记录点(u, v)可以到的下一点为v
Memory[v][u] = u; //记录点(v, u)可以到的下一点为u
}
best = MAXINT;
floyd();
//输出
if (best == MAXINT)
{
printf("No solution./n");
}
else
{
for (i = 0; i < num; ++i)
{
printf("%d", result[i] + 1);
if (i != num - 1)
{
putchar(' ');
}
else
{
putchar('/n');
}
}
}
return 0;
}
五、memory:316k time:32ms