感慨
好久没在csdn发作品了,洛谷自从5月就再也没刷过题了,算法已经永远也不写了,哈哈哈就连c++都没写了,转到学习java之后,每天都在接触无限好玩的事情,三个月里的时间我简单学习了javase,javaweb,自己部署了一个linux的cenos的服务器http://47.108.173.205/login?redirect=%2Findexhttp://47.108.173.205/login?redirect=%2Findex当然也是为了我们的c++大作业的可视化(结果好像老师不让用一点java,呃呃呃呃),学习了一些简单的linux的指令,并为了一些竞赛学习了nlp,接触语言模型的时候感受到了他的魅力,先接触的mirai部署了自己的QQ机器人,通过Yiri-mirai写出自己的机器人时候真的兴奋,在网页部署成功chatglm,目前正在学习langchainchatchat(说起来也好笑竞赛需要的模型居然前端不是vue,是python的Streamlit.,尝试了很久通过vue对接上个chatchat的后端一直失败,哎还是只能从头学习Streamlit,气气气被迫去学python了),哎项目也要烂尾了哈哈哈没时间抱怨了快点进入正题。
思路
简单的实现自反,对称,传递闭包,首先我们要把关系转化成矩阵,比如<a,b>的关系就代表矩阵 中(0,1)坐标为1。
自反闭包就是矩阵的对称轴都是1。
对称闭包就是(x,y)为1的话,(y,x)也为1。
传递闭包就是Warshall算法,大家在离散中学过就不多赘述,简单的模拟。
细节好像没什么细节,挺简单的//
应付老师代码
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<algorithm>
#include<queue>
#include<cstring>
#include<string>
#include<unordered_map>
using namespace std;
int n; //代表关系的数量
struct node
{
char l;
char r;
}text[100], arr[100];
int mp[100][100];
int change[100][100];
void Init()
{
n = 4;
text[0].l = 'a', text[0].r = 'b';
text[1].l = 'b', text[1].r = 'a';
text[2].l = 'b', text[2].r = 'c';
text[3].l = 'c', text[3].r = 'd';
}
void Print()
{
printf("{");
int lx, ly; //找出最后的关系在哪里
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
if (change[i][j]) lx = i,ly = j;
}
}
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
if (change[i][j])
{
if (i == lx && j == ly) printf("<%c,%c>", 'a' + i, 'a' + j);
else printf("<%c,%c>,", 'a' + i, 'a'+j);
}
}
}
printf("}\n");
}
int main()
{
Init();
for (int i = 0; i < 4; i++)
{
int x, y;
x = text[i].l - 'a';
y = text[i].r - 'a';
mp[x][y] = 1;
}
memcpy(change, mp, sizeof mp);
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
printf("%d",mp[i][j]);
}
printf("\n");
}
printf("\n");
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
printf("%d", change[i][j]);
}
printf("\n");
}
Print();
//自反闭包
memcpy(change, mp, sizeof mp);
for (int i = 0; i < n; i++)
{
change[i][i] = 1;
}
Print();
//对称闭包
memcpy(change, mp, sizeof mp);
for (int i = 0; i < n; i++)
{
for(int j=0;j<n;j++)
if(change[i][j]) change[j][i]=1;
}
Print();
//传递闭包
memcpy(change, mp, sizeof mp);
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
if (change[j][i])
{
for (int k = 0; k < n; k++)
{
change[j][k] = change[j][k] | change[i][k];//逻辑加
}
}
}
}
Print();
return 0;
}
补充完整代码
因为老师要求的只需要打印一个关系就可以了,我们为了学习当然要写一个可以应付大部分情况的代码,因此我就把代码补充完整了
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<algorithm>
#include<queue>
#include<cstring>
#include<string>
#include<unordered_map>
using namespace std;
int n; //代表关系的数量
struct node
{
char l;
char r;
}text[100], arr[100];
int mp[100][100];
int change[100][100];
FILE* pf = fopen("closure.txt", "w");
void Init()
{
n = 4;
text[0].l = 'a', text[0].r = 'b';
text[1].l = 'b', text[1].r = 'a';
text[2].l = 'b', text[2].r = 'c';
text[3].l = 'c', text[3].r = 'd';
}
void Print()
{
printf("{");
fprintf(pf, "{");
int lx, ly; //找出最后的关系在哪里
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
if (change[i][j]) lx = i,ly = j;
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
if (change[i][j])
if (i == lx && j == ly) printf("<%c,%c>", 'a' + i, 'a' + j), fprintf(pf, "<%c,%c>", 'a' + i, 'a' + j);
else printf("<%c,%c>,", 'a' + i, 'a'+j),fprintf(pf, "<%c,%c>,", 'a' + i, 'a' + j);
printf("}\n");
fprintf(pf, "}\n");
}
int main()
{
int t;
printf("输入1就是打印老师要求的矩阵的,其他的需要自己输入关系");
scanf("%d",&t);
if (t == 1) //自己拓展的
{
Init();
for (int i = 0; i < n; i++)
{
int x, y;
x = text[i].l - 'a';
y = text[i].r - 'a';
mp[x][y] = 1;
}
}
else
{
printf("请输入n的值");
scanf("%d",&n);
for (int i = 0; i < n; i++)
{
char a, b;
scanf("\n"); //吃掉回车,不可取掉
scanf("%c %c", &a, &b);
int x, y;
x = a - 'a';
y = b - 'a';
mp[x][y] = 1;
}
}
memcpy(change, mp, sizeof mp); //保存初始状态
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
printf("%d",mp[i][j]);
}
printf("\n");
}
printf("\n");
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
printf("%d", change[i][j]);
}
printf("\n");
}
fprintf(pf, "初始关系\n");
Print();
printf("\n");
//自反闭包
printf("自反闭包\n");
fprintf(pf, "自反闭包\n");
memcpy(change, mp, sizeof mp);
for (int i = 0; i < n; i++)
change[i][i] = 1;
Print();
//对称闭包
printf("对称闭包\n");
fprintf(pf, "对称闭包\n");
memcpy(change, mp, sizeof mp);
for (int i = 0; i < n; i++)
for(int j=0;j<n;j++)
if(change[i][j]) change[j][i]=1;
Print();
//传递闭包 Warshall算法
printf("传递闭包\n");
fprintf(pf, "传递闭包\n");
memcpy(change, mp, sizeof mp);
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
if (change[j][i])
for (int k = 0; k < n; k++)
change[j][k] = change[j][k] | change[i][k];//逻辑加
Print();
fclose(pf);
pf = NULL;
return 0; //听说大佬都是不加return的
}