This is a very good shortest path + deep search exercise
Question surface:
Copy heard from Lu Niu that there are many treasures buried in a god field called yz, so copy came to this God land divided into regions. Lu Niu told me that there are treasures here, which are placed in the PI (1 < = Pi < = n) area. Copy also knows the distance between each area. Now start from area 1, get all the treasures and leave in area n. I'm very lazy, so I have to come to you to find a suitable route for him, so that he can walk the shortest distance.
Note: there is a sentence in the title
Note that the distance i to j is not necessarily equal to the distance j to i.
That is to say, when reading in, we need to consider the edge processing
It can also be said that this is a two-way graph with unequal weights
After getting the question surface, you can analyze:
1. We need to know the distance from each point to the treasure point
2. There are many possibilities to complete the treasure points here. We need to traverse them one by one
So what is the algorithm that satisfies these two conditions at the same time:
1. floyd
2. Depth first search
First of all, we need to memorize floyd's board:
void floyd(int n) { for (int k = 1; k <= n; k++) { //First, enumerate the transit points k for (int i = 1; i <= n; i++) { for (int j = 1; j <= n; j++) { if (dis[i][k] != 0 && dis[k][j] != 0) { dis[i][j] = Min(dis[i][j], dis[i][k] + dis[k][j]); } } } } }
Using the idea of dynamic programming, we find the shortest distance between each point
Then we'll do a deep search
Before that, we have to deal with parameters and read in problems
There is a sentence in the question:
Next, an N*N matrix. The number in row i+1 and column j represents the distance between regions I and j
Then we can read:
memset(dis, INF, sizeof(dis)); //Initialize infinity to facilitate dynamic programming for (int i = 1; i <= n; i++) { for (int j = 1; j <= n; j++) { long long w; cin >> w; dis[i][j] = Min(dis[i][j], w); //Handle heavy edges } }
If you don't understand, you can compare the read subscript with the title
Now we know that there are p treasure points, so we can save the points with an array of a
Then there is the parameter problem
In the process of deep search, we need to pass in three parameters
At the same time, we use ans to record the best answer
1. Current point
2. The remaining treasure points to traverse
3. Total distance traveled (used to optimize ans)
Then, in order to avoid repeated traversal, we mark with the flag array
We can get the following code
void dfs(int now, int m, long long sum) { if (m == 0) { //After traversing all treasure points ans = min(sum + dis[now][n], ans); //optimization return; //to flash back } for (int i = 1; i <= p; i++) { //Enumerate a total of p treasure points if (!flag[i]) { //If not accessed flag[i] = 1; //sign dfs(a[i], m - 1, sum + dis[now][a[i]]); //(when you reach the next treasure point, there are m-1 treasure points left. The total distance sum plus the distance from the current point to the treasure point) flag[i] = 0; //Backtracking retag not accessed } } }
Finally, we can output the best answer ans
Complete code
#include <bits/stdc++.h> //luogu 1690 by zqy #define maxn 105 #define INF 0x3f3f3f3f using namespace std; long long dis[maxn][maxn], n; long long a[maxn], ans = INF; bool flag[15]; int p; int Min(long long x, long long y) {return x < y ? x : y;} void floyd(int n) { for (int k = 1; k <= n; k++) { for (int i = 1; i <= n; i++) { for (int j = 1; j <= n; j++) { if (dis[i][k] != 0 && dis[k][j] != 0) { dis[i][j] = Min(dis[i][j], dis[i][k] + dis[k][j]); } } } } } void dfs(int now, int m, long long sum) { if (m == 0) { ans = min(sum + dis[now][n], ans); return; } for (int i = 1; i <= p; i++) { if (!flag[i]) { flag[i] = 1; dfs(a[i], m - 1, sum + dis[now][a[i]]); flag[i] = 0; } } } int main() { cin >> n; memset(dis, INF, sizeof(dis)); for (int i = 1; i <= n; i++) { for (int j = 1; j <= n; j++) { long long w; cin >> w; dis[i][j] = Min(dis[i][j], w); //Handle heavy edges } } cin >> p; for (int i = 1; i <= p; i++) { cin >> a[i]; } floyd(n); dfs(1, p, 0); cout << ans << endl; return 0; }
Sprinkle flowers
Konjaku is very weak. Please be tolerant