花了两天多的时间看了集合论的大部分内容,主要还是在了解定义定理和证明,练的题还不够,以后有时间还得练习巩固。很多问题还是一知半解的,还是得开学认真听课做题吧,有很多总结得不清楚的,见谅~
今天来码一遍Warshall算法,首先来回顾一下:
考虑一个n+1个矩阵序列M0,M1…Mn,将矩阵Mk的第I行j列的元素记为Mk[i,j],对于k=0,1,2…n Mk[i,j]=1当且仅当在R的关系图存在一条vi到vj的路径,并且这条路径除端点外中间只经过{v1,v2,…vk}中的结点,而M0是R的关系矩阵,Mn对应R的传递闭包。Warshall算法从M0开始顺序计算直到Mn为止。
假设Mk已经计算完毕,接下来需要计算Mk+1,对于每一组i,j确定Mk+1[I,j]是否为1,等于1当且仅当在R的关系图中存在一条从vi到vj并且中间只经过{v1,v2…vk+1}的路径,这种路径分两类:
第一类:只经过{v1,v2…vk}这时Mk[ij]=1
第二类:经过了vk+1的路径,因为回路可从路径中删除,考虑经过vk+1一次的路径,这条路径可分成两段,从xi到xk+1再从xk+1到xj,有Mk[i,k+1]=1,Mk[k+1,j]=1。
即让Mk[I,k+1]=1 ^ Mk[k+1,j]=1为真就行了
把两类情况并起来,就组成了算法的核心部分
上代码:
#include<iostream>
int i,j,k,n;
int matrix[100][100];
void PaintMatrix()
{
std::cout<<"------------"<<std::endl;
for(int m=1;m<=n;m++)
{
for(int t=1;t<=n;t++)
{
std::cout<<matrix[m][t]<<" ";
}
std::cout<<std::endl;
}
}
int main()
{
//std::cout<<"please input number"<<std::endl;
std::cin>>n;
//std::cout<<"input matrix"<<std::endl;
for(int a=1;a<=n;a++)
{
for(int b=1;b<=n;b++)
{
std::cin>>matrix[a][b];
}
}
//warshall
for(k=1;k<=n;k++)
{
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
{
matrix[i][j]=matrix[i][j]|(matrix[i][k]&matrix[k][j]);
}
}
PaintMatrix();
}
}
了解了原理实现起来就很简单了,把书上例题运行结果贴上来感受一下
附上其他学习笔记内容