离散数学:生成主范式

这里写图片描述

样例输入1

PQR

3 m

000

010

101

样例输出1

(P\vee Q\vee \neg R)\wedge (P\vee \neg Q\vee \neg R)\wedge (\neg P\vee Q\vee R)\wedge (\neg P\vee \neg Q\vee R)\wedge (\neg P\vee \neg Q\vee \neg R)

(\neg P\wedge \neg Q\wedge \neg R)\vee (\neg P\wedge Q\wedge \neg R)\vee (P\wedge \neg Q\wedge R)

样例输入2

PQR

3 M

000

010

101

样例输出2

(P\vee Q\vee R)\wedge (P\vee \neg Q\vee R)\wedge (\neg P\vee Q\vee \neg R)

(\neg P\wedge \neg Q\wedge R)\vee (\neg P\wedge Q\wedge R)\vee (P\wedge \neg Q\wedge \neg R)\vee (P\wedge Q\wedge \neg R)\vee (P\wedge Q\wedge R)

样例输入3

PQ

0 m

样例输出3

(P\vee Q)\wedge (P\vee \neg Q)\wedge (\neg P\vee Q)\wedge (\neg P\vee \neg Q)

NULL

样例输入4

PQ

0 m

样例输出4
我自己添加的,自己下载源代码自己测试,当时第一遍写根本没想到这种情况,提交后总有两组测试数据报错才发现的

注:这里多哔哔几句,作为本专科生,涉及到字符串操作第一反应是采用java处理,可惜平台java代码不能正常测试,只能提交C和C++,这二者当然是选择C++才是明智的,不过我想大部分人和我一样大学C只学了基础C++和C#学了也早就忘光了,那就只能通过C来往麻烦里写了。
  我用C写了10个小时,300多行代码,舍友大神用C++只用了5个小时100多行代码,所以相比之下哪个更适合显而易见。
  下边先粘代码(带着测试输出的代码,不过都被注释掉了,看不懂的打开自己琢磨,也有相应注释),思路放在最后,方便伸手党,毕竟我也是,下边是我自己写的纯C的,涉及字符字符串所以用了很多野路子,还是只保证满分过,代码质量相当垃圾
  一下代码在VC6.0和gcc编译器下都能正常运行

#include<stdio.h>
#include<malloc.h>
#include<string.h>
#include<math.h>

void small(char *elem, int *p1,int position);
void big(char *elem, int *p1,int position);
void change(int pre,int elemLen,int *p1[1024],int position);
void twoChangeTen(char *num1,int num2,int *p4);
void my_print(char *c,int i,int num);
int main(){
	char *elem;//用于接收输入的PQR
	int elemLen;
	int rowNum;
	char bigOrSmall;
	int *p1[1024];//指针数组,用来存储整个字典,//这里[]中的数要足够大,不然会溢出,直接完蛋
	char *p2[10];//用来存储每一行的01输入,因为2<n<10,所以最多有10个字符
	int i;
	int totol;
	int *p4;//用来标识字典那个位置是用户输入的
	char c[7]={'\\','w','e','d','g','e',' '};
	char d[5]={'\\','v','e','e',' '};
	int temp = 0;

	//--------------数据输入部分---------------
	elem = (char*) malloc(sizeof(char));
	//gets(elem);//第一行输入原子命题
	scanf("%s",elem);
	scanf("%d %c",&rowNum,&bigOrSmall);//第二行输入
	/*for(i=0;i<=rowNum;i++){//用于接收后续所有01输入行
		char* row;
		row = (char*) malloc(sizeof(char));
		gets(row);
		p1[i] = row;
	}*/

	elemLen = strlen(elem);
	totol = (int)pow(2,elemLen);

	p4 = (int *)malloc(sizeof(int) * totol);
	//对p4置为0
	for(i = 0;i<totol;i++){
		*(p4 + i) = 0;
	}

	for(i=0;i<rowNum;i++){//用于接收后续所有01输入行
		char* row;
		row = (char*) malloc(sizeof(char) * 10);
		//gets(row);
		scanf("%s",row);
		p2[i] = row;
		twoChangeTen(p2[i],elemLen,p4);
		//printf("row===%s\n",row);
	}

	//--------------数据输出部分----------------
	//printf("\n%s\n",elem);
	//printf("%d %c\n",rowNum,bigOrSmall);//这里如果下边输出指针数组的话没用\n换行就出现了换行效果?
	//printf("%d\n",elemLen);
	//测试生成字典
	//totol = (int)pow(2,elemLen);
	for(i=0;i<totol;i++){
		change(i,elemLen,p1,i);
	}

	//测试p1
	int j;
	int k = 0;//记录所需的组数,删掉最后多余的输出
	int *k1;//记录每组的下标
	k1 = (int *)malloc(sizeof(int) * totol);
	/*for(i=0;i<totol;i++){
		printf("p1[%d]",i);
		for(j=0;j<elemLen;j++){
			printf("%d",p1[i][j]);
		}
		printf("\n");
	}*/

	//测试p4
	/*for(i=0;i<totol;i++){
		printf("p4_%d=%d\n",i,*(p4+i));
	}*/
	
	/*for(i=0;i<=rowNum;i++){
		printf("%s\n",p1[i]);
	}*/

	if(bigOrSmall=='m'){
		if(rowNum==0){
			for(i=0;i<totol;i++){
				printf("(");
				big(elem, p1[i],i);
				printf(")");
				if(i<totol-1){
					//printf("%s",c);
					//printf("Len==%d",strlen(c));//13
					for(j=0;j<7;j++){
						printf("%c",c[j]);
					}
				}
			}
			printf("\nNULL\n");
		}else if(rowNum==totol){
			printf("NULL\n");
			for(i=0;i<totol;i++){
				printf("(");
				small(elem, p1[i],i);
				printf(")");
				if(i<totol-1){
					//printf("%s",c);
					//printf("Len==%d",strlen(c));//13
					for(j=0;j<5;j++){
						printf("%c",d[j]);
					}
				}
			}
			printf("\n");
		}else{
			//打印第一行
			for(i=0;i<totol;i++){
				if(p4[i]==0){
					k++;
				}
			}

			temp=0;
			for(i=0;i<totol;i++){
				if(p4[i]==0){
					temp++;
					printf("(");
					big(elem, p1[i],i);
					printf(")");
					if(temp<k){
						//printf("%s",c);
						//printf("Len==%d",strlen(c));//13
						for(j=0;j<7;j++){
							printf("%c",c[j]);
						}
					}
				}
				
			}
			//printf("\b\b\b\b\b\b\b");
			//printf("%c%c%c%c%c%c%c",'*','*','*','*','*','*','*');
			//printf("%c",'\n');
			printf("\n");
			k=0;
			//打印第二行
			for(i=0;i<totol;i++){
				if(p4[i]==1){
					k++;
				}
			}

			temp=0;
			for(i=0;i<totol;i++){
				if(p4[i]==1){
					temp++;
					printf("(");
					small(elem, p1[i],i);
					printf(")");
					if(temp<k){
						//printf("%s",c);
						//printf("Len==%d",strlen(c));//13
						for(j=0;j<5;j++){
							printf("%c",d[j]);
						}
					}
				}
				
			}
			//printf("\b\b\b\b\b\b\b");
			printf("\n");
			k=0;
		}
	}else if(bigOrSmall=='M'){
		if(rowNum==0){
			printf("NULL\n");
			for(i=0;i<totol;i++){
				printf("(");
				small(elem, p1[i],i);
				printf(")");
				if(i<totol-1){
					//printf("%s",c);
					//printf("Len==%d",strlen(c));//13
					for(j=0;j<5;j++){
						printf("%c",d[j]);
					}
				}
			}
			printf("\n");
			
		}else if(rowNum==totol){
			for(i=0;i<totol;i++){
				printf("(");
				big(elem, p1[i],i);
				printf(")");
				if(i<totol-1){
					//printf("%s",c);
					//printf("Len==%d",strlen(c));//13
					for(j=0;j<7;j++){
						printf("%c",c[j]);
					}
				}
			}
			printf("\nNULL\n");
		}else{
			//打印第一行
			for(i=0;i<totol;i++){
				if(p4[i]==1){
					k++;
				}
			}

			temp=0;
			for(i=0;i<totol;i++){
				if(p4[i]==1){
					temp++;
					printf("(");
					big(elem, p1[i],i);
					printf(")");
					if(temp<k){
						//printf("%s",c);
						//printf("Len==%d",strlen(c));//13
						for(j=0;j<7;j++){
							printf("%c",c[j]);
						}
					}
				}
				
			}
			//printf("\b\b\b\b\b\b\b");
			//printf("%c%c%c%c%c%c%c",'*','*','*','*','*','*','*');
			//printf("%c",'\n');
			printf("\n");
			k=0;
			//打印第二行
			for(i=0;i<totol;i++){
				if(p4[i]==0){
					k++;
				}
			}

			temp=0;
			for(i=0;i<totol;i++){
				if(p4[i]==0){
					temp++;
					printf("(");
					small(elem, p1[i],i);
					printf(")");
					if(temp<k){
						//printf("%s",c);
						//printf("Len==%d",strlen(c));//13
						for(j=0;j<5;j++){
							printf("%c",d[j]);
						}
					}
				}
				
			}
			//printf("\b\b\b\b\b\b\b");
			printf("\n");
			k=0;
		}
	}
	/*
		else if(bigOrSmall=='M'){
		if(rowNum==0){
			small(totol,p1);
			printf("NULL");
		}else{
			small(totol-rowNum,p1);
			big(rowNum,p1);
		}
	}
	*/
	return 0;
}

//p1是所有的字典,p4是所需字典对应的位置
void small(char *elem, int *p1,int position){
	char *row1;//输入的原命题
	int *row2;//输入的01
	int row_pos = 0;
	char row1_elem;
	int row2_elem;
	char a[2]={' ','T'};//1
	char b[6]={'\\','n','e','g',' ','T'};//0
	char c[7]={'\\','w','e','d','g','e',' '};
	char d[5]={'\\','v','e','e',' '};
	int i = 0;
	int pre = 0;

	/*row1 = (char*) malloc(sizeof(char));
	gets(row1);
	row2 = (char*) malloc(sizeof(char));
	gets(row2);*/
	row1 = (char*) malloc(sizeof(char));
	row2 = (int*) malloc(sizeof(int));
	row1 = elem;
	row2 = p1;

	for(row_pos; row_pos < strlen(row1); row_pos++){
		row1_elem = *(row1+row_pos);
		row2_elem = *(row2+row_pos);
		if(row2_elem == 0){
			b[5] = row1_elem;
			my_print(b,0,6);
		}else{
			a[1] = row1_elem;
			if(pre = 1){
				my_print(a,1,2);//a,1,2
			}else{
				my_print(a,0,2);
			}	
		}
		if(row_pos < strlen(row1)-1){
			my_print(c,0,7);
		}
		pre = row1_elem;
		
	}
}//small


//p1是p1[]的一行
void big(char *elem, int *p1,int position){
	char *row1;
	int *row2;
	int row_pos = 0;
	char row1_elem;
	int row2_elem;
	char a[2]={' ','T'};//0
	char b[6]={'\\','n','e','g',' ','T'};//1
	char c[5]={'\\','v','e','e',' '};
	char d[7]={'\\','w','e','d','g','e',' '};
	int i = 0;
	char pre = 1;

	/*row1 = (char*) malloc(sizeof(char));
	gets(row1);
	row2 = (char*) malloc(sizeof(char));
	gets(row2);*/

	row1 = (char*) malloc(sizeof(char));
	row2 = (int*) malloc(sizeof(int));
	row1 = elem;
	row2 = p1;
	/*printf("bigRow2===");
	for(i=0;i<strlen(row1);i++){
		printf("%d",*(row2+i));
	}
	printf("\n");*///拿到的数据没问题

	for(row_pos; row_pos < strlen(row1); row_pos++){
		row1_elem = *(row1+row_pos);
		row2_elem = *(row2+row_pos);
		if(row2_elem == 0){
			a[1] = row1_elem;
			if(row_pos ==0){
				my_print(a,1,2);
			}else{
				my_print(a,1,2);
			}
			
		}else if(row2_elem == 1){
			b[5] = row1_elem;
			my_print(b,0,6);
		}
		if(row_pos < strlen(row1)-1){
			my_print(c,0,5);
		}
		pre = row2_elem;
		
	}
}


void change(int pre,int elemLen,int *p1[1024],int position){
	//printf("=========%d",pre);
	int* after;
	int* row;
	row = (int*) malloc(sizeof(int) * elemLen);
	after = (int*) malloc(sizeof(int) * elemLen);
	int i,j,t;

	if(position==0){
		//所有位置置为0
		for(j=0;j<elemLen;j++){
			*(row+j) = 0;
		}
		p1[0] = row;
	}else{
		//printf("------------");
		//转化为二进制
		for(i=0;pre!=0;i++){
			*(after+i) = pre % 2;
			pre = pre / 2;
			//printf("%d",*(after+i));
		}
		//printf("------------\n");

		i--;

		//所有位置置为0
		for(j=0;j<elemLen;j++){
			*(row+j) = 0;
		}

		t=0;
		//填充
		for(j=1;i>=0;j++){
			*(row+elemLen-j) = *(after+t);
			//printf("(%d-%d)",elemLen-j,*(row+elemLen-j));
			i--;
			t++;
		}

		//打印结果
		/*for(j=0;j<elemLen;j++){
			printf("%d",*(row+j));
		}
		printf("\n");*/

		p1[position] = row;

		/*printf("-------------test---------------\n");
		for(i=0;i<elemLen;i++){
			printf("%d",p1[position][i]);
		}*/
		//printf("\n");//已经存进字典了
	}
	
}
//num1代表二进制的字符串,num2表示字符个数
void twoChangeTen(char *num1,int num2,int *p4){
	int i;
	int t;//在做转换时用到
	char getC1;//取到每个二进制的字符
	int *p3;//用来存放所有转换来的整形数
	int z = 0;//最后的结果

	p3 = (int *)malloc(sizeof(int) * num2);
	for(i=0;i<num2;i++){
		getC1 = *(num1+i);
		t = (int)(getC1 - '0');
		//printf("t=======%d\n",t);
		*(p3 + i) = t;
	}

	for(i=0;i<num2;i++){
		t = *(p3 + num2 - i -1);
		z += t * (int)pow(2,i);
	}

	//printf("z===%d",z);
	*(p4 + z) = 1;//代表该位置存了数
}

void my_print(char *c,int i,int num){
	for(i;i<num;i++){
		printf("%c",c[i]);
	}
}

代码很多冗余,比如main方法中的字符数组只用到了c,d其他都没用到,直接就从前两个代码里copy过来了,复用率嘛,等着你自己优化吧,我已经写到吐了
下边是思路:

  1. 如果没做过前两个生成极小项和极大项的题目,那么推荐你先去看那两个题,做出来后可以吧前两个程序代码稍作修改抽成方法或者函数直接调用
  2. 首先实现数据的输入和存储,这是第一步,考虑多行‘01010101…’数据应该是什么类型,怎么存储
  3. 多行‘01010101…’输入是按照字典序的,但不是连续的,这又该怎么办
  4. 看输出样子,肯定是用循环来输出,那么控制条件是什么,怎么确定是加括号还是\wedge或者\vee

下边是我的解决思路,具体代码看上边

  1. 多行‘0101…’代码放到字符型的指针数组里,因为PQR…对多有10个,所以一行最多2到1024个字符,这里自己区分指针数组和数组指针
  2. 自己生成字典,通过一个辅助的字典下标数组来存储用户输入的数据在字典的哪个位置,这里涉及到二进制与十进制的转换问题和如何把字符型的‘01’字符转换成相应的整形,注意这不是java
  3. 解决了上述问题就解决了70%了,剩下的是字符的输出,我并没有存储而是直接循环输出到屏幕,这里可能会出现在最后多输出一个\wedge或者\vee的情况,输出到控制台后字符只能替换不能删除,所以用转义字符\b也就失去了意义,我用的是最笨的办法,多用一个循环和一个控制变量,具体的自己去代码分析
    4.最后 把之前的生成极小项和极大项的代码拿过来抽成一个方法,放到循环里,循环调用,打印输出即可
    5…
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值