Java算法小练习之联结词02
这篇文章将以题目为导向性,带领大家见识一些以联结词为知识背景的算法小练习
- 双条件联结词
- 求“(P∨Q)∧(P→R)∧(Q→R)”成真赋值
- 输出“(P∨Q)∧(P→R)∧(Q→R)”真值表
1.双条件联结词
就从这道双条件联结词切入
题目描述
给定原子变元P、Q的真值(用1表示T,用0表示F),求命题公式P⇄Q的真值。
输入描述
输入原子变元P、Q的真值(1或0),用空格隔开。
输出描述
输出命题公式P⇄Q的真值(1或0)。
样例输入
1 1
样例输出
1
知识点
联结词
提示
对输入的P、Q,直接输出表达式“P==Q”的值即可。
看符号我们可以得知:我们要求p等价于q的真值
回想我们之前举过的例子:今天星期五,明天必然是星期六;今天不是星期五,明天也必然不是星期六。要求两个条件同时成立或不成立双条件式才成立。
所以我们在代码中的判断条件就是我们输入的p与q是否相同即可
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int p = sc.nextInt();
int q = sc.nextInt();
if(p==q){
System.out.println(1);
}else{
System.out.println(0);
}
sc.close();
}
}
可能我们会一下子想不起来等价于的具体条件,但是我们可以通过例子来复盘复原出双条件式成立的条件。
好的,到此这道双条件联结词也就此结束。
我们继续前进,看下一道题目。
2.求“(P∨Q)∧(P→R)∧(Q→R)”成真赋值
题目描述
编程求命题合式公式(P∨Q)∧(P→R)∧(Q→R)取值为T时的赋值(即P、Q、R的值)。禁止采用手工演算列出真值表,再用输出语句输出答案。
输入描述
无输入。
输出描述
按字典序输出该合式公式取值为T时的所有赋值(即P、Q、R的值,1或0,用空格隔开),每种赋值占一行。
样例输入
无输入。
样例输出
0 1 1 (仅给出第1行输出作为示例)
这道题目看起来就比上一道和前面一篇的例题要略复杂一些,那么思路从何而来呢?
题干中有一句话:禁止采用手工演算列出真值表,这不妨给了我们些许思路。
当我们没有代码思路时,通常是因为我们没有用计算机的方式来分析和理解问题。在处理有限范围的问题时,枚举法(穷举法)是常用的最简单的解决方案。
因为其实如果能通过相对容易的穷举得出的答案我们又需要计算机干嘛呢,计算机就需要解决不易穷举的问题,这就依赖于我们给出的算法策略机制。
机器本身并不直接“理解”枚举法的概念,但它可以通过执行代码来实现这一点。
我们需要利用数据结构等相关知识编写有效的算法,让计算机通过系统化地遍历所有可能的情况来找到最合适的解决方案。
通过将问题分解为可执行的步骤,并利用计算机的强大计算能力,我们能够在较短时间内获得结果。
但作为人,我们在没有思路的情况下,不妨先尝试着进行一些枚举,看看是否能从中总结出一些代码层面上的规律。
用换元法的思路来看这个式子,我们可以将这道题目转换为:
在x、y、z分别取值什么情况下,合式x∧y∧z为真?
这个符号为合取符号,合取式要求我们每个合取项都为真,即x、y、z分别都为真。
然后我们再细看x、y、z三个项分别什么情况下为真,这里就是利用了有分解问题的思维方法,最后当思路进行到这里的时候可以类比一下函数中的复合函数。
并且三个合取项都为真的条件非常苛刻,所以如果题目问的是什么时候取T什么时候取F,我们就可以将为真的条件放在if判断里,else直接输出F,更为有效且精准。
x 真 ------> P∨Q 真 ------> p析取q ------> p、q两者有一及以上为真即可
y 真 ------> P→R 真 ------> 若p则r ------> 若p真则r也必须为真,p假则r真假随意
z 真 ------> Q→R 真 ------> 若q则r ------> 若q真则r也必须为真,q假则r真假随意
注意区分:
- 析取是∨像漏斗一样的符号,析~析出~用漏斗过滤析出
- 合取是∧,像大山一样的符号,合力~山
当以p为核心时,枚举部分实例:
- 当p取值为1时,q真假随意,但r必须为真
- 当p取值为0时,q必须为真,且r也必须为真
这道题目写到这里又有一个新发现:r值在此题中为定值1,所以写法可以更加优化
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
for(int p = 0; p <= 1; p++){
for(int q = 0; q <= 1; q++){
// for(int r = 0; r <= 1; r++){
int r = 1;
if(p==0){
q=1;
// r=1;
System.out.println(p+" "+q+" "+r);
} else if (p==1) {
// r=1;
System.out.println(p+" "+q+" "+r);
} else if (q==0) {
p=1;
// r=1;
System.out.println(p+" "+q+" "+r);
} else if (q==1) {
// r=1;
System.out.println(p+" "+q+" "+r);
}
// else if (r==0) {
// q=0;
// p=1;
// System.out.println(p+" "+q+" "+r);
// } else if (r==1) {
// System.out.println(p+" "+q+" "+r);
// }
// }
}
}
scan.close();
}
}
优化后的代码为:
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
for(int p = 0; p <= 1; p++){
for(int q = 0; q <= 1; q++){
int r = 1;
if(p==0){
q=1;
System.out.println(p+" "+q+" "+r);
} else if (p==1) {
System.out.println(p+" "+q+" "+r);
} else if (q==0) {
p=1;
System.out.println(p+" "+q+" "+r);
} else if (q==1) {
System.out.println(p+" "+q+" "+r);
}
}
}
scan.close();
}
}
因为pq二者必定有其一为真,所以无论如何r必须为1,这道题其实到这里我们已经很清楚答案了011或者101再或者111三种答案。
在这里我们再参考一个别人给出的解:
翻译一下就是满足p=1或者q=1 并且 p=0或者r=1 并且 q=0或者r=1的条件下输出,似乎有些奇怪,我在他的基础上改了改:
源代码:
import java.util.Scanner;
// 1:无需package
// 2: 类名必须Main, 不可修改
public class Main {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
for (int i=0;i<=1;i++){
for(int j = 0;j<=1;j++){
for (int k=0;k<=1;k++){
if (((i==1)||(j==1))&&((i==0)||(k==1))&&((j==0)||(k==1))){
System.out.println(i+" "+j+" "+k);
}
}
}
}
scan.close();
}
}
修改后代码:
import java.util.Scanner;
// 1:无需package
// 2: 类名必须Main, 不可修改
public class Main {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int k = 1;
for (int i=0;i<=1;i++){
for(int j = 0;j<=1;j++){
if (((i==1)&&(j==1))||((i==0)&&(j==1))||((j==0)&&(i==1))){
System.out.println(i+" "+j+" "+k);
}
}
}
scan.close();
}
}
3.输出“(P∨Q)∧(P→R)∧(Q→R)”真值表
题目描述
编程输出命题合式公式(P∨Q)∧(P→R)∧(Q→R)的真值表。 禁止采用手工画出真值表,再用输出语句输出整个真值表。
输入描述
无输入。
输出描述
输出该命题公式的真值表,前两行示例如下。
P Q R -> (P|Q)&(P->R)&(Q->R)
0 0 0 -> 0
这道题算是第二道的拓展应用:且应用了我们刚才所说的将较为苛刻的判断条件放在if中,其余则为else。注意输出格式要严格按照题目要求,注意空格,不然会报错!!
import java.util.Scanner;
// 1:无需package
// 2: 类名必须Main, 不可修改
public class Main {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
System.out.println("P Q R -> (P|Q)&(P->R)&(Q->R)");
for(int p = 0; p <= 1; p++){
for(int q = 0; q <= 1; q++){
for(int r = 0; r <= 1; r++){
if(p==0&&q==1&&r==1 || p==1&&q==0&&r==1 || p==1&&q==1&&r==1){
System.out.println(p+" "+q+" "+r+" "+"->"+" "+1);
}else{
System.out.println(p+" "+q+" "+r+" "+"->"+" "+0);
}
}
}
}
scan.close();
}
}
下一篇会再深入一些,涉及合式公式﹁(P→Q)∧(P⇄R) ,比如一些条件联结词的优先级、真值表等等。
原文地址:https://blog.csdn.net/2301_77139967/article/details/145113009
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!