最短路径问题
今天这个问题主要和Dijkstra和Floyd这两种算法有关,第一个用于定点到固定点,第二个可用于任一点到任一点。
先说一下今天遇到的调试的一些问题,在vs里边会出现
错误 1 error C4996: ‘scanf’: This function or variable may be unsafe. Consider using scanf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details. g:\code\c\test_10_29\test_10_29\main.c 7 1 test_10_29
这样的错误,这是调试器的问题,可以在<stdio.h>头文件前加一行这样的代码,
#define _CRT_SECURE_NO_WARNINGS
当然还有其他解决办法,这里先写这一种。
在说一下这几天的感受吧,感觉算法真的挺难,需要自己好好琢磨,只看教程虽然有用,但还是要理解,不懂的话可以可以先看一些别人的源代码,照着学,看大佬们写的流程,一点一点理解,然后自己敲一遍,不对再比对,找bug,然后调整。重要还是还是要理解。还是要多练,自己这点还是很欠缺的,做一会好像就不太想学了。得慢慢改正。
然后就是今天的题了
这道题可以用今天学的两种算法解,我只用了第一种。第一种比较麻烦一点,主要是还是理解算法思想。这道题基本就是按照算法的基础来的。
代码如下:
/*#pragma once
//#pragma once是一个比较常用的C/C++杂注,
//只要在头文件的最开始加入这条杂注,
//就能够保证头文件只被编译一次*/
/*#include<iostream>//dijsktra
#include<stdio.h>
#include<string.h>
#define INF 0x3f3f3f3f
using namespace std;
void Dijkstra(int n);
int mp[105][105],dis[105];
bool vis[105];
int main()
{
int a, b, c,N,M;
while (cin >> N >> M && (N != 0 && M != 0))
{
for (int i = 1; i <= 105; i++)
for(int j = 1;j <= 105;j++)
mp[i][j] = INF;
for (int i = 1; i <= M; i++)
{
cin >> a >> b >> c;
mp[a][b] = mp[b][a] = c;
}
Dijkstra(N);
cout << dis[N] << endl;
}
system("pause");
return 0;
}
void Dijkstra(int n)
{
int minx, flag = 1;
for (int i = 1; i <= n; i++)
{
dis[i] = mp[1][i];
vis[i] = true;
}
vis[1] = false;
for (int i = 1; i <= n; i++)
{
minx = INF;
for (int j = 1; j <= n; j++)
{
if (vis[j] && dis[j] < minx)//选取到这个位置的最短距离
{
flag = j;//记录位置
minx = dis[j];
}
}
vis[flag] = false;
if (minx == INF)//如果都访问过,退出循环
break;
for (int j = 1; j <= n; j++)
{
if (vis[j] && mp[flag][j] + dis[flag] < dis[j])
dis[j] = mp[flag][j] + dis[flag];
}
}
}*/
//Floyd(弗洛伊德算法)
//#define _CRT_SECURE_NO_WARNINGS//除去scanf函数函数安全问题
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
#define MAX 105
#define INF 1e9
int mp[MAX][MAX];
int n, m, a, b, c;
int main()
{
while (~scanf("%d%d", &n, &m)) {
if (n == 0 && m == 0) break;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
mp[i][j] = INF;
for (int i = 1; i <= m; i++) {
scanf("%d%d%d", &a, &b, &c);
mp[a][b] = mp[b][a] = c;
}
for (int k = 1; k <= n; k++)
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
mp[i][j] = min(mp[i][j], mp[i][k] + mp[k][j]);
cout << mp[1][n] << endl;
}
return 0;
}
这道题和第一题一样,都是算法的基础运用,但要知道这道题是从0开始,不能只知道套用模板。
代码如下:
#include<iostream>
#include<string.h>
#define INF 0x3f3f3f3f
using namespace std;
bool vis[205];
int mp[205][205],dis[205],N,M;
void Dijkstra(int start);
int main()
{
int a,b,c;
while (cin>>N>>M)
{
for (int i = 0; i < 205; i++)
for (int j = 0; j < 205; j++)
{
if (i == j)
mp[i][j] = 0;//当i和j相等时,距离为零
else
mp[i][j] = INF;
}
for (int i = 0; i < M; i++)
{
cin >> a >> b >> c;
if(mp[a][b] > c)//这点很重要
mp[a][b] = mp[b][a] = c;
}
int S, T;
cin >> S >> T;
Dijkstra(S);
if (dis[T] == INF)
printf("-1\n");
//cout << -1 << endl;
else
printf("%d\n", dis[T]);
//cout << dis[T] << endl;
}
return 0;
}
void Dijkstra(int start)
{
int minx, flag = start;
for (int i = 0; i < N; i++)
{
dis[i] = mp[start][i];
vis[i] = true;
}
vis[flag] = false;
dis[flag] = 0;
for (int i = 0; i < N; i++)
{
minx = INF;
for (int j = 0; j < N; j++)
{
if (vis[j] && dis[j] < minx)
{
minx = dis[j];
flag = j;
}
}
vis[flag] = false;
if (minx == INF)
break;
for (int j = 0; j < N; j++)
{
if (vis[j] && dis[flag] + mp[flag][j] < dis[j])
dis[j] = dis[flag] + mp[flag][j];
}
}
}
这道题加了另一个参数,花费问题,其实就是在模板里边加一个类似于距离的变量,然后最后比较一下,在距离相同时,选择最少的花费。
代码如下:
//#include<iostream>
#define _CRT_SECURE_NO_WARNINGS//该语句必须在#include<stdio.h>之前,否则还会报错
//This function or variable may be unsafe.”警告的解决办法
#include<stdio.h>
#define INF 0x3f3f3f3f
using namespace std;
void Dijkstra(int s);
int n, m, mp[1005][1005], dis[1005], cs[1005],cost [1005][1005];
bool vis[1005];
int main()
{
while (scanf("%d%d",&n,&m)&&n!=0&&m!=0)
{
for(int i = 1;i < 1005;i++)
for (int j = 1; j < 1005; j++)
{
if (i == j)
{
mp[i][j] = 0;
cost[i][j] = 0;
}
else
{
mp[i][j] = INF;
cost[i][j] = INF;
}
}
for (int i = 1; i <= m; i++)
{
int a, b, d, p;
scanf("%d%d%d%d", &a, &b, &d, &p);
//cin >> a >> b >> d >> p;
if (mp[a][b] > d)
{
mp[a][b] = mp[b][a] = d;
cost[a][b] = cost[b][a] = p;
}
}
int s, t;
scanf("%d%d", &s, &t);
//cin >> s >> t;
Dijkstra(s);
printf("%d %d\n", dis[t], cs[t]);
//cout << dis[t] <<" "<< cs[t] << endl;
}
return 0;
}
void Dijkstra(int s)
{
int minx, flag, minc;
for (int i = 1; i <= n; i++)
{
dis[i] = mp[s][i];
cs[i] = cost[s][i];
vis[i] = true;
}
vis[s] = false;
dis[s] = 0;
cs[s] = 0;
for (int i = 1; i <= n; i++)
{
minx = INF;
minc = INF;
for (int j = 1; j <= n; j++)
{
if (vis[j] && dis[j] < minx)
{
minx = dis[j];
minc = cs[j];
flag = j;
}
}
vis[flag] = false;
if (dis[flag] == INF)
break;
for (int j = 1; j <= n; j++)
{
if (vis[j] && dis[j] > dis[flag] + mp[flag][j])
{
dis[j] = dis[flag] + mp[flag][j];
cs[j] = cs[flag] + cost[flag][j];
}
else if (vis[j] && dis[j] == dis[flag] + mp[flag][j])
cs[j] = cs[flag] + cost[flag][j];
}
}
}