Part1:Floyd
初始邻接矩阵:
[[0 6 13],
[10 0 4],
[5 ∞ 0]]
Floyd 算法的执行过程
A A(-1) A(0) A(1) A(2)
V0 V1 V2 V0 V1 V2 V0 V1 V2 V0 V1 V2
V0 0 6 13 0 6 13 0 6 10 0 6 10
V1 10 0 4 10 0 min(23,4) 10 0 4 9 0 4
V2 5 ∞ 0 5 11 0 5 11 0 5 11 0
c动态数组:
void fun( int **array)
c静态数组:
void fun( int array[][D])
void Func(int array[3][10])
void fun( int (*array)[D])
函数内部两种访问数组的方式都可以:
array[i][j]
*( *(array+i) + j)
Floyd 函数
# include<bits/stdc++.h>
using namespace std;
//遍历所有边回到起点的最短路径
class Solution{
private:
//最短路径矩阵
void Floyd(vector<vector<int>>&graph,int N){
// N个顶点
for(int k=1;k<=N;++k){
for(int i=1;i<=N;++i){
for(int j=1;j<=N;++j){
if(i==j){
continue;
}
// k与i和j都相连
if(graph[i][k]!=-1&&graph[k][j]!=-1){
graph[i][j]= graph[i][j]==-1 ? graph[i][k]+graph[k][j]:min(graph[i][j],graph[i][k]+graph[k][j]);
}
}
}
}
}
Part2: dp 求最短路径
最短路径
遍历所有的组合情况,求出最短的组合方式,
例如比较 d(2,8)+d(4,6),d(2,6)+d(4,8), d(2,4)+d(6,8), 然后取最小值即为最终的优化方案:d(2,8)+d(4,6)。
求解该步骤的时候,可以使用DFS来寻找最短路径方案,也可以利用DFS的思想,改为动态规划来实现,(状压dp)。
动态规划思路的代码相对没有DFS更符合人们的思路,答题思路是构造一个dp表,行值为1,列值表示该集合中所含的元素,
奇度数数组的所有组合: 2^ods(包括空组合)
例如:集合7表示所含元素在奇度数组中下标为{1, 2, 3}的集合,0、1、2、3、12、13、23、123
e.g.:假设现在得到的奇数度点的数组为:[2,4,6,8](实际上该数组在后续代码的实现上是[0,2,4,6,8])
一共有四个有效点,则dp数组应为1×16的规模,
dp[0] 表示一个点也没有的集合,空集自然距离也为0,
而更大集合j的最短距离值,应该由更小的集合i及不在i中的两个点x,y求得
e.g.:当求出集合3({2, 4})的最短距离时,记录在dp[3]中,
而集合15({2,4,6,8})的最短距离可以用dp[3] + d[6][8]来完成更新,
如果dp[3]+d[6][8]<dp[15],则更新dp[15]。
同理,当求出集合5({2,6})的最短距离时,记录在dp[5]中,则可以用dp[5]+d[4][8]<dp[15],则更新dp[15],该动态规划算法通过利用小数据集更新大数据集的距离,最终返回dp的最后一个值作为最优路径的结果。
public:
int shortestPath (vector<vector<int>>& graph, vector<int>& dev, int N) {
// 最短路径矩阵
Floyd (graph, N);
// 度数为奇数的点集odds
vector<int> odds;
// 在奇数度集合odds后添加0
odds.push_back(0);
for (int i=1; i<=N; ++i) {
// 按位与 : n转换为二进制与1进行按位与运算 (返回奇数度)
if (dev[i]&1) {
//odds保存奇数度顶点
odds.push_back(i);
}
}
// 查看odds
//for(int i=0;i<odds.size();i++){
// cout << odds[i];
//}
// 奇数度顶点个数ods
int ods = odds.size()-1;
// 二进制1向左移位ods=2位,二进制100=4
vector<int> dp((1<<ods), -1);
//查看dp.size()=4
//cout << dp.size() <<endl;
dp[0] = 0;
for (int i=0; i<(1<<ods); ++i) {
int x = 1;
// i= 0,1,2,3. 1&i
while ((1<<(x-1)) & i) {
// 如果i是奇数,x=2。
++x;
//2,2,3
//cout<<x<<endl;
}
// i=0 x=1,y=2.
for (int y=x+1; y<=ods; ++y) {
// 10 & 0=0 不执行
if ((1<<(y-1)) & i) {
continue;
}
// x-1=0,y-1=1
// dp[ 0|1|2 ]/dp[3] = graph[1][3]
// -12 2 3
// cout << 0|1|2;
// 三目运算符扩展(见博客)??::
dp[i|(1<<(x-1))|(1<<(y-1))] =
// x到y的路径存在且dp存在
dp[i] != -1 && graph[odds[x]][odds[y]] != -1 ?
// dp[3]=-1
dp[i|(1<<(x-1))|(1<<(y-1))] == -1 ?
// dp[3]不存在:dp[3]=dp[0]+graph[1][3]:
dp[i]+graph[odds[x]][odds[y]] :
//dp[3]存在:dp[0]+graph[1][3]
min(dp[i|(1<<(x-1))|(1<<(y-1))], dp[i]+graph[odds[x]][odds[y]])
//x到y路径不存在:dp[3]
: dp[i|(1<<(x-1))|(1<<(y-1))];
}
}
//2^ods(奇数度顶点个数)
return dp[(1<<ods)-1];
}
Part3: 主函数
主函数
int main()
{
// N为顶点,R为边
int N,R;
cin >> N >> R;
// graph初始化为-1,第一行和第一列是空出的。
vector<vector<int>> graph(N+1,vector<int>(N+1,-1));
// 度数,初始化为0
vector<int> dev(N+1,0);
int res=0;
// routes:顶点1和2的距离为3,以此类推。
vector<vector<int>> routes={{1,2,3},{2,3,4},{3,4,5},{1,4,10},{1,3,12}};
// 由routes构造邻接矩阵graph
for(int i=0;i<R;++i){
int x=routes[i][0],y=routes[i][1],z=routes[i][2];
graph[x][y]=z;
graph[y][x]=z;
//dev保存节点的度
++dev[x]; ++dev[y];
// res是遍历路径长度,因为要遍历所有边并回到起点,所以res+=每条route
res +=z;
}
// 所有边之和
cout << res <<endl;
//dev:0,3,2,3,2
//for(int i=0;i<=N;i++){
// cout << dev[i];
//}
//cout<<" "<<endl;
Solution solve;
res += solve.shortestPath(graph,dev,N);
// 遍历所有边回到起点的最短路径
cout << res <<endl;
3:不满足第一个条件
//只满足第二个条件
//int res_test1 = res==0 ? res==41 ? 1: 2: 3;
//双条件都不满足
//int res_test4 = res==0 ? res==1 ? 1: 2: 3;
///2 只满足第一个条件,不满足第二个条件
//int res_test2 = res==41 ? res==0 ? 1: 2: 3;
///1 双条件都满足
//int res_test3 = res==41 ? res!=0 ? 1: 2: 3;
// 加括号,有优先级顺序
//cout<< (res==41 ? 41 : 0) <<endl;
//cout << res_test1 <<endl;
//cout << res_test2 <<endl;
//cout << res_test3 <<endl;
//cout << res_test4 <<endl;
//二进制运算 或
//3 = 11(二进制)
//cout<< (0|1|2) <<endl;
//1 = 1
//cout<< (0|1) <<endl;
//1 = 1
//cout<< (1|1) <<endl;
return 0;
}
graph: 已求得的最短路径结果。
dev数组: 所有节点的度。
odds数组: 选择奇数度的节点组成。
dp数组: 初始化为-1。
参考:https://blog.csdn.net/qq_29592167/article/details/90246438
https://blog.csdn.net/junruitian/article/details/63253501