sicily Catch the thief

来源:互联网 发布:脸萌软件苹果版 编辑:程序博客网 时间:2024/06/07 04:55

这次期末因为一些意料之外的烦心事搞的无心复习,无心考试,感觉考得都不怎么样,连算法机考也一团糟。很不甘。虽然这样了,还是可以继续学习算法吧,就算不为什么功利的目的,既然喜欢那就坚持好了。

题目

Description
A thief has robbed a bank in city 1 and he wants to go to city N. The police know that the thief will choose the shortest path to get to his destination. As there may be multiple shortest paths, the police want to calculate the number of all the cities that the thief may visit. (Including city 1 and city N)

Input
The input may contain several test cases.

Each test case starts with a line containing an integer N, indicating the number of cities.

The next N lines describe a N*N matrix A. the jth element in the ith row indicates the distance between city i and city j is Aij (Aij=Aji). Aij=-1 means city i and city j is not connected.

N=0 indicates the end of the input.

Output
For each test case, just print the total number of the cities the thief may visit in a single line.

Sample Input
Copy sample input to clipboard
5
0 1 4 -1 -1
1 0 -1 2 -1
4 -1 0 -1 2
-1 2 -1 0 3
-1 -1 2 3 0
0

Sample Output
5
Problem Source: 期末模拟题C

分析

相当于要求两点间所有的最短路,有两种方法。
1. floyd算法做,求出任意两点间的最短路之后再判断每个点是否在起点和终点的最短路上,假设起点是1,终点是n,则对于一个点i若有minDist[1][i]+minDist[i][n]==minDist[1][n]则该点在在1到n的最短路上。非常容易理解,不过也需要动脑筋才能想到,还有就是这题没给出n的范围,一开始可能不太敢想floyd这种O(n3)的算法。
2. dijkstra算法做。这也是我最初的想法。但需要对dijkstra算法做一点改动,每次加入一个最近点后要保存所有能到达这个点的最短路的上一个点,最后dfs找出所有的点即可。dijkstra算法是O(n2)的,比floyd算法快。

代码

  1. floyd
#include <iostream>#include <cstring>#include <algorithm>#include <string>#include <queue>#include <vector>#include <cstdio>#include <stack>#include <cmath>using namespace std;#define LL long longconst int inf=99999999;#define N 1001int minDist[N][N];int n;int main(){    while(scanf("%d",&n)&&n)    {                       for(int i=1;i<=n;i++)            for(int j=1;j<=n;j++)            {                scanf("%d",&minDist[i][j]);                if(minDist[i][j]==-1)                    minDist[i][j]=inf;            }        //floyd算法求任意两点间最短路         for(int k=1;k<=n;k++)            for(int i=1;i<=n;i++)                for(int j=1;j<=n;j++)                    if(minDist[i][j]>minDist[i][k]+minDist[k][j])                        minDist[i][j]=minDist[i][k]+minDist[k][j];        int ans=2;        for(int i=2;i<n;i++)            if(minDist[1][i]+minDist[i][n]==minDist[1][n])                ans++;        printf("%d\n",ans);    }}
  1. dijkstra
#include <iostream>#include <cstring>#include <algorithm>#include <string>#include <queue>#include <vector>#include <cstdio>#include <stack>#include <cmath>using namespace std;#define LL long longconst int inf=99999999;#define N 1001int road[N][N];bool vis[N];bool vis2[N];int dist[N];vector<int> pre[N];int n; int ans;void dijkstra(){    memset(vis,0,sizeof(vis));    for(int i=0;i<N;i++) dist[i]=inf;    for(int i=0;i<N;i++) pre[i].clear();    dist[1]=0;    for(int i=1;i<=n;i++)    {        int pos=-1;        int Min=inf;        for(int j=1;j<=n;j++)        {            if(!vis[j]&&dist[j]<Min)            {                Min=dist[j];                pos=j;            }        }        if(pos==-1) break;        vis[pos]=1;        for(int j=1;j<=n;j++)            if(!vis[j]&&road[pos][j]+Min<dist[j])                dist[j]=road[pos][j]+Min;        /*找到所有可到达这点的最短路*/        for(int j=1;j<=n;j++)        {            if(vis[j]&&j!=pos&&dist[pos]==dist[j]+road[j][pos])                pre[pos].push_back(j);        }    }}void dfs(int city){    vis2[city]=1;    if(city==1)         return;    for(int i=0;i<pre[city].size();i++)    {        if(!vis2[pre[city][i]])            dfs(pre[city][i]);    }}int main(){    while(scanf("%d",&n)&&n)    {        memset(vis,0,sizeof(vis));        memset(road,0,sizeof(vis));        memset(vis2,0,sizeof(vis2));        ans=0;        for(int i=1;i<=n;i++)            for(int j=1;j<=n;j++)            {                scanf("%d",&road[i][j]);                if(road[i][j]==-1)                    road[i][j]=inf;            }        dijkstra();        dfs(n);        for(int i=1;i<=n;i++)            if(vis2[i]) ans++;        //cout<<dist[n]<<endl;        printf("%d\n",ans);    }}

这道题拖了几天,最出来后想想是挺简单的题,说到底还是对最短路算法的理解不够深。

0 0