题目:略。
解答:今天(2018/8/29)我将迪杰斯特拉算法复习了下,收获良多,然后将其用邻接矩阵和邻接链表都实现了下,今晚刷了PAT甲级中的1072 Gas Station(30 分)、1003 Emergency(25 分)和1030 Travel Plan(30 分),都是最短路径问题,其中1072题应该是比较烦的了,花的时间也比较久,但思路都相同,dijkstra算法的实现在我另一篇博客中Disjkstra最短路径-算法题总结进行了分析。
今天(2018/8/30)在PAT上又找到一道相似的题目1087 All Roads Lead to Rome(30 分),也是用dijkstra算法实现,比较满意。
这四题的AC代码如下:
1003题AC代码:
/*1003题,用邻接链表实现*/
#include<iostream>
#include<algorithm>
#include<vector>
#include<cstdio>
#define maxn 510
#define inf 100000000
using namespace std;
typedef struct{
int v, dis;
}node;
int n, m, c1, c2;
vector<node> e[maxn];
int dis[maxn];
bool visited[maxn] = { false };
int weight[maxn]; //记录各点的点权
int w[maxn]; //记录各点的累积最大点权
int num[maxn]; //记录最短路径的数量
void dijkstra(int s)
{
dis[s] = 0; num[s] = 1;
for (int i = 0; i < n; ++i)
{
int u = -1, mindis = inf;
for (int j = 0; j < n; ++j)
{
if (visited[j] == false && mindis > dis[j])
{
mindis = dis[j];
u = j;
}
}
if (u == -1) return;
visited[u] = true;
for (int k = 0; k < e[u].size(); ++k)
{
int v = e[u][k].v;
if (dis[u] + e[u][k].dis < dis[v])
{
dis[v] = dis[u] + e[u][k].dis;
num[v] = num[u];
w[v] = w[u] + weight[v];
}
else if (dis[u] + e[u][k].dis == dis[v])
{
num[v] += num[u];
if (w[v] < w[u] + weight[v])
{
w[v] = w[u] + weight[v];
}
}
}
}
}
int main()
{
cin >> n >> m >> c1 >> c2;
fill(dis, dis + maxn, inf);
for (int i = 0; i < n; ++i)
{
cin >> weight[i];
w[i] = weight[i];
}
for (int i = 0; i < m; ++i)
{
int v1, v2, d;
node tmp;
cin >> v1 >> v2 >> d;
tmp.dis = d; tmp.v = v1;
e[v2].push_back(tmp);
tmp.v = v2;
e[v1].push_back(tmp);
}
dijkstra(c1);
cout << num[c2] << " " << w[c2] << endl;
return 0;
}
1030题AC代码:
#include<cstdio>
#include<iostream>
#include<vector>
#define inf 1000
#define maxn 510
using namespace std;
typedef struct{
int v, dis, cost;
}node;
int n, m, s, d;
int dis[maxn];
bool visited[maxn] = { false };
int tcost[maxn];
int pre[maxn];
vector<node> e[maxn];
void disjkstra(int s)
{
dis[s] = 0; tcost[s] = 0;
for (int i = 0; i < n; ++i)
{
int u = -1, mindis = inf;
for (int j = 0; j < n; ++j)
{
if (visited[j] == false && dis[j] < mindis)
{
mindis = dis[j];
u = j;
}
}
if (u == -1) return;
visited[u] = true;
for (int k = 0; k < e[u].size(); ++k)
{
int v = e[u][k].v;
//输出
//cout << v << endl;
if (visited[v] == false)
{
if (dis[u] + e[u][k].dis < dis[v])
{
dis[v] = dis[u] + e[u][k].dis;
pre[v] = u;
tcost[v] = tcost[u] + e[u][k].cost;
}
else if (dis[u] + e[u][k].dis == dis[v] && tcost[v] > tcost[u] + e[u][k].cost)
{
pre[v] = u;
tcost[v] = tcost[u] + e[u][k].cost;
}
}
}
// cout << endl;
}
}
void dfs(int s, int d)
{
if (s == d)
{
printf("%d ", s);
return;
}
dfs(s, pre[d]);
printf("%d ", d);
}
int main()
{
cin >> n >> m >> s >> d;
fill(dis, dis + maxn, inf);
fill(dis, dis + maxn, inf);
for (int i = 0; i < n; ++i) pre[i] = i;
for (int i = 0; i < m; ++i)
{
int v1, v2, distance, cost;
node tmp;
cin >> v1 >> v2 >> distance >> cost;
tmp.v = v2; tmp.dis = distance; tmp.cost = cost;
e[v1].push_back(tmp);
tmp.v = v1;
e[v2].push_back(tmp);
}
disjkstra(s);
//输出路径
dfs(s, d);
//输出最短路径
cout << dis[d] << " ";
//输出最小花费
cout << tcost[d] << endl;
return 0;
}
1072题代码:
#include<cstdio>
#include<iostream>
#include<vector>
#include<string>
#include<sstream>
#define maxn 1015
#define inf 100000000
using namespace std;
typedef struct{
int v, dis;
}node;
int n, m, k, d;
vector<node> e[maxn];
int dis[maxn];
bool visited[maxn] = { false };
int getseq(const string& s)
{
stringstream ss;
int seq;
if (s.front() != 'G')
{
ss.str(s);
ss >> seq;
return seq;
}
else
{
ss.str(s.substr(1));
ss >> seq;
//cout << "seq:" << seq << endl;
return (seq + n);
}
}
void dijkstra(int s)
{
dis[s] = 0;
for (int i = 0; i < n+m; ++i)
{
int u = -1, mindis = inf;
for (int j = 1; j <= n+m; ++j)
{
if (visited[j] == false && mindis > dis[j])
{
u = j;
mindis = dis[j];
}
}
if (u == -1) return;
visited[u] = true;
for (int j = 0; j < e[u].size(); ++j)
{
int v = e[u][j].v;
if (visited[v] == false && dis[v] > dis[u] + e[u][j].dis)
{
dis[v] = dis[u] + e[u][j].dis;
}
}
}
}
int main()
{
cin >> n >> m >> k >> d;
for (int i = 0; i < k; ++i)
{
string id1, id2; int distance;
cin >> id1 >> id2 >> distance;
int v1 = getseq(id1), v2 = getseq(id2);
//cout << v1 << " " << v2 << " " << distance;
node tmp;
tmp.dis = distance; tmp.v = v2;
e[v1].push_back(tmp);
tmp.v = v1;
e[v2].push_back(tmp);
}
int flag = false; //记录是否有方案
int gas = n;
double mindis = 0, tdis = 0, avgdis = inf;
for (int s = n + 1; s <= n + m; ++s)
{
fill(visited, visited + maxn, 0);
/*for (int r = n + 1; r <= n + m; ++r)
{
if (r != s) visited[r] = true;
}
*/
fill(dis, dis + maxn, inf);
dijkstra(s);
//输出结果
/*for (int i = 1; i <= n + m; ++i)
{
cout << dis[i] << " ";
}
*/
//cout << endl;
//判断距离是否都在范围内
bool isok = true;
double tmp_tdis = 0, tmp_avgdis = inf, tmp_mindis = inf;
for (int i = 1; i <= n; ++i)
{
tmp_tdis += dis[i];
tmp_mindis = tmp_mindis > dis[i] ? dis[i] : tmp_mindis;
if (dis[i] > d)
{
isok = false; break;
}
}
if (isok == false) continue;
//将最小平均距离的gas station记录下来
tmp_avgdis = tmp_tdis / n;
//cout << tmp_tdis << " " << tmp_mindis << endl;
if (tmp_mindis > mindis)
{
avgdis = tmp_avgdis;
mindis = tmp_mindis;
gas = s - n;
flag = true;
}
else if (tmp_mindis == mindis && tmp_avgdis < avgdis)
{
avgdis = tmp_avgdis;
mindis = tmp_mindis;
gas = s - n;
flag = true;
}
//cout << avgdis << " " << mindis << endl;
}
if (flag == true)
{
cout << 'G' << gas << endl;
printf("%.1f %.1f\n", mindis, avgdis);
}
else
{
printf("No Solution\n");
}
return 0;
}
1087题AC代码如下:
#include<iostream>
#include<vector>
#include<string>
#define maxn 220
#define inf 1000000
using namespace std;
typedef struct{
int v, dis;
}node;
int dis[maxn];
int happy[maxn];
bool visited[maxn] = { false };
int pre[maxn];
vector<node> e[maxn];
vector<string> names;
int h[maxn];
int num[maxn];
int n, k;
int getIndex(const string& name)
{
for (int i = 0; i < names.size(); ++i)
{
if (names[i] == name) return i;
}
return -1;
}
void dijkstra(int s)
{
dis[s] = 0; num[s] = 1;
for (int i = 0; i < n; ++i)
{
int u = -1, mindis = inf;
for (int j = 0; j < n; ++j)
{
if (visited[j] == false && mindis > dis[j])
{
u = j;
mindis = dis[j];
}
}
if (u == -1) return;
visited[u] = true;
for (int p = 0; p < e[u].size(); ++p)
{
int v = e[u][p].v;
if (visited[v] == false)
{
if (dis[v] > dis[u] + e[u][p].dis)
{
dis[v] = dis[u] + e[u][p].dis;
h[v] = h[u] + happy[v];
pre[v] = u;
num[v] = num[u];
}
else if (dis[v] == dis[u] + e[u][p].dis)
{
if (h[v] < h[u] + happy[v])
{
h[v] = h[u] + happy[v];
pre[v] = u;
}
num[v] += num[u];
}
}
}
}
}
void dfs(int s, int v)
{
if (s == v)
{
cout << names[s] << "->";
return;
}
dfs(s, pre[v]);
if(names[v] == "ROM") cout << names[v];
else cout << names[v] << "->";
}
void dfs_count(int s, int v, int& count)
{
if (s == v)
{
return;
}
dfs_count(s, pre[v], ++count);
}
int main()
{
string start;
cin >> n >> k >> start;
names.push_back(start); happy[0] = 0;
for (int i = 1; i <= n - 1; ++i)
{
string v; int happies;
cin >> v >> happies;
names.push_back(v); happy[i] = happies;
}
//初始化h数组
fill(h, h + maxn, 0);
//初始化dis数组
fill(dis, dis + maxn, inf);
//初始化num数组
fill(num, num + maxn, 0);
//记录路径
for (int i = 0; i < k; ++i)
{
string v1, v2; int d;
cin >> v1 >> v2 >> d;
int iv1 = getIndex(v1), iv2 = getIndex(v2);
node tmp; tmp.dis = d;
tmp.v = iv1;
e[iv2].push_back(tmp);
tmp.v = iv2;
e[iv1].push_back(tmp);
}
int s = getIndex(start);
dijkstra(s);
//输出结果
int count = 0;
int v = getIndex("ROM");
cout << num[v] << " " << dis[v] << " " << h[v] << " ";
dfs_count(s, v, count);
cout << h[v] / count << endl;
dfs(s, v);
return 0;
}