标准的方案应该是当做最短路问题来解决,但是这道数据量很小,完全可以用DFS或者BFS搜索暴力解决。
题目中指出,只会将乘客目的地作为路线中的站点。因此,排除了某种情况下,绕路走一个不是目的地的位置反而更省距离的可能。换句话说,只可能从出发点去往某个目的地,或者从某个目的地去往另一个目的地。这道题求得最短距离是路径的权值和,而不是搜索过程中的层数或者步数之类的东西,因此不要在找到第一个可行方案后就完成搜索(结束循环),第一个可行方案意味着步数最少,但不意味着是这道题中的最短路径。甚至,这道题中的每一个可行方案的步数都是相同的。既然如此,使用BFS或者DFS便没有什么区别了,自然考虑实现起来更简便的DFS算法。
暴力搜索,每种方案都是搜够所有的目标点为止,取距离(路径权值和)最小的方案。
#include <iostream>
#include <cstring>
using namespace std;
int cnt,ans,n,k;
int vis[30],map[30][30],mask[30],stop[30];
int DFS(int num,int now,int d)
{
if(num==cnt)
{
ans=min(ans,d);
return 0;
}
for(int i=0;i<cnt;i++)
{
if(!vis[i])
{
vis[i]=1;
DFS(num+1, stop[i], d+map[now][stop[i]]);
vis[i]=0;
}
}
return 0;
}
int main()
{
while(scanf("%d",&n)==1&&n)
{
memset(vis, 0, sizeof(vis));
memset(mask, 0, sizeof(mask));
cnt=0;
ans=1000000;
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
scanf("%d",&map[i][j]);
scanf("%d",&k);
for(int i=0;i<k;i++)
{
int t;
scanf("%d",&t);
if(!mask[t])
{
mask[t]=1;
stop[cnt++]=t;
}
}
DFS(0, 0, 0);
printf("%d\n",ans);
}
return 0;
}
以下为原本写的BFS求解方案。显然不如DFS简洁。
#include <iostream>
#include<stdio.h>
#include<string.h>
#include<queue>
using namespace std;
int main() {
int n;
while(scanf("%d",&n)==1 && n)
{
int way[30][30],wanted[30];
struct tra
{
int stop[30];
int now,len;
}t;
queue<tra> q;
memset(wanted,0,sizeof(wanted));
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
scanf("%d",&way[i][j]);
int z,want;
scanf("%d",&z);
for(int i=0;i<z;i++)
{
scanf("%d",&want);
wanted[want]=1;
}
t.stop[0]=1;
t.now=0;
t.len=0;
for(int i=1;i<n;i++)
t.stop[i]=0;
q.push(t);
int length=1000000000,k=0;
while(!q.empty())
{
tra f=q.front();
q.pop();
k=1;
for(int i=1;i<n;i++)
if(wanted[i] && !f.stop[i])
{
tra f2=f;
f2.stop[i]=1;
f2.len+=way[f2.now][i];
f2.now=i;
q.push(f2);
k=0;
}
if(k==1&&f.len<length)
length=f.len;
}
printf("%d\n",length);
}
return 0;
}