西南交通大学离散数学第三次大作业

感慨

好久没在csdn发作品了,洛谷自从5月就再也没刷过题了,算法已经永远也不写了,哈哈哈就连c++都没写了,转到学习java之后,每天都在接触无限好玩的事情,三个月里的时间我简单学习了javase,javaweb,自己部署了一个linux的cenos的服务器http://47.108.173.205/login?redirect=%2Findexicon-default.png?t=N7T8http://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的
}

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值