穷举法的基本思想是根据题目的部分条件确定答案的大致范围,并在此范围内对所有可能的情况逐一验证,直到全部情况验证完毕。若某个情况验证符合题目的全部条件,则为本问题的一个解;若全部情况验证后都不符合题目的全部条件,则本题无解。
用笔穷举的速度非常慢,《谁养鱼》是爱因斯坦在20世纪初出的谜语,他说世界上有百分之98的人答不出来。你能答出来吗?
这道逻辑性很强的题是:
1)在一条街上有5座房子,喷了5种颜色。
2)每个房子里住着不同国籍的人.
3)每个人喝不同的饮料,抽不同品牌的香烟,养不同的宠物。
问题是:谁养的是鱼?
所列举项应该满足如下15个要求:
主程序:
public static void main(String args[]) {
//Java程序主入口
rw33 test=new rw33();//实例化对象
long l=System.currentTimeMillis();//获得系统时间
test.calculate();//调用的方法进行计算统计
System.out.println("计算共用时:"+(System.currentTimeMillis()-l)+"ms");//获得计算所花费的时间
}
计算一组数据的组合方式:
public void init() {
//计算一组数据的组合方式
ArrayList array=new ArrayList();//创建集合数组
for(int num1=0;num1<5;num1++) {
for(int num2=0;num2<5;num2++) {
if(num2==num1)
continue;
for(int num3=0;num3<5;num3++) {
if(num3 ==num2||num3==num1)
continue;
for(int num4 =0;num4<5;num4++) {
if(num4==num3||num4==num2||num4==num1)
continue;
for (int num5=0;num5<5;num5++) {
if(num5==num4||num5==num3||num5==num2||num5==num1)
continue;
int oneArray[]= {num1,num2,num3,num4,num5};
array.add(oneArray);
}
}
}
}
}
color=new int[array.size()][5];//创建颜色的二维数组
for(int count=0;count<array.size();count++) {
//循环数组时初始化房子颜色数据
color[count]=(int[])array.get(count);
}
person=color;
drink=color;
smoke=color;
pet = color;
}
判断运算:
public void calculate() {
//判断运算
init();//调用方法时初始化数据
for(int num1=0;num1<color.length;num1++) {
if(!con4(num1))
continue;
if(!con14(num1))
continue;
for(int num2=0;num2<person.length;num2++) {
if(!con1(num2,num1))
continue;
if(!con9(num2))
continue;
for(int num3=0;num3<drink.length;num3++) {
if(!con3(num2,num3))
continue;
if(!con5(num1,num3))
continue;
if(!con8(num3))
continue;
for(int num4=0;num4<smoke.length;num4++) {
if(!con7(num1,num4))
continue;
if(!con12(num4,num3))
continue;
if(!con13(num2,num4))
continue;
if(!con15(num4,num3))
continue;
for(int num5=0;num5<pet.length;num5++) {
if(!con2(num2,num5))
continue;
if(!con6(num4,num5))
continue;
if(!con10(num4,num5))
continue;
if(!con11(num5,num4))
continue;
total++;
show(num1,num2,num3,num4,num5);
}
}
}
}
}
}
满足所列举项的条件:
public boolean con1(int cy,int cl) {
//英国人住红色房子
for(int i=0;i<5;i++) {
if(person[cl][i]==0) {
if(color[cy][i]==0) {
return true;
}else
break;
}
}
return false;
}
public boolean con2(int cy,int p) {
//瑞典人养狗
for(int i=0;i<5;i++) {
if(person[cy][i]==1) {
if(pet[p][i]==0) {
return true;
}else
break;
}
}
return false;
}
public boolean con3(int cy,int d) {
//丹麦人喝茶
for(int i=0;i<5;i++) {
if(person[cy][i]==2) {
if(drink[d][i]==0) {
return true;
}else
break;
}
}
return false;
}
public boolean con4(int cl) {
//绿色房子在白色房子左面
int c1=0;//白房子
int c2=0;//绿房子
for(int i=0;i<5;i++) {
if(color[cl][i]==1) {
c1=i;
}
if(color[cl][i]==2) {
c2=i;
}
}
if(c2<c1)
return true;
else
return false;
}
public boolean con5(int cl,int d) {
//绿色房子的主人喝咖啡
for(int i=0;i<5;i++) {
if(color[cl][i]==2) {
if(drink[d][i]==1) {
return true;
}else
break;
}
}
return false;
}
public boolean con6(int s,int p) {
//抽PalMal香烟的人养鸟
for(int i=0;i<5;i++) {
if(smoke[s][i]==0) {
if(pet[p][i]==1) {
return true;
}else
break;
}
}
return false;
}
public boolean con7(int cl,int s) {
//黄色房子主人抽Dunhill香烟
for(int i=0;i<5;i++) {
if(color[cl][i]==4) {
if(smoke[s][i]==1) {
return true;
}else
break;
}
}
return false;
}
public boolean con8(int d) {
//住在中间房子的人喝牛奶
if(drink[d][2]==2)
return true;
else
return false;
}
public boolean con9(int cy) {
//挪威人住第一间房
if(person[cy][0]==3)
return true;
else
return false;
}
public boolean con10(int s,int p) {
//抽Blends香烟的人住在养猫人隔壁
for(int i=0;i<5;i++) {
if(smoke[s][i]==4) {
if(i<4&&pet[p][i+1]==2) {
return true;
}
if(i>0&&pet[p][i-1]==2) {
return true;
}
break;
}
}
return false;
}
public boolean con11(int p,int s) {
//养马的人住抽Dunhill香烟的人隔壁
for(int i=0;i<5;i++) {
if(pet[p][i]==3) {
if(i<4&&smoke[s][i+1]==1) {
return true;
}
if(i>0&&smoke[s][i-1]==1) {
return true;
}
break;
}
}
return false;
}
public boolean con12(int s,int d) {
//抽BlMt的人喝啤酒
for(int i=0;i<5;i++) {
if(smoke[s][i]==2) {
if(drink[d][i]==3) {
return true;
}else
break;
}
}
return false;
}
public boolean con13(int cy,int s) {
//德国人抽Prince香烟
for(int i=0;i<5;i++) {
if(person[cy][i]==4) {
if(smoke[s][i]==3) {
return true;
}else
break;
}
}
return false;
}
public boolean con14(int c) {
//挪威人住蓝色房子隔壁
if(color[c][1]==3)
return true;
else
return false;
}
public boolean con15(int s,int d) {
//抽Blends香烟的人有一个喝水的邻居
for(int i=0;i<5;i++) {
if(smoke[s][i]==4) {
if(i<4&&drink[d][i+1]==4) {
return true;
}
if(i>0&&drink[d][i-1]==4) {
return true;
}
break;
}
}
return false;
}
显示计算之后的每个数组找出对应答案:
public void show(int n1,int n2,int n3,int n4,int n5) {
//显示计算之后的每个数组找出对应答案
System.out.println("第"+total+"组:>");
System.out.println("1\t\t2\t\t3\t\t4\t\t5\t\t");
for(int i=0;i<5;i++)//循环显示房子数组数据
System.out.print(HOUSES[color[n1][i]]+"\t\t");
System.out.println();
for(int i=0;i<5;i++)//循环显示人员数组数据
System.out.print(PERSONS[person[n2][i]]+"\t\t");
System.out.println();
for(int i=0;i<5;i++)//循环显示饮料数组数据
System.out.print(DRINKS[drink[n3][i]]+"\t\t");
System.out.println();
for(int i=0;i<5;i++)//循环显示烟数组数据
System.out.print(SMOKES[smoke[n4][i]]+"\t\t");
System.out.println();
for(int i=0;i<5;i++)//循环显示宠物数组数据
System.out.print(PETS[pet[n5][i]]+"\t\t");
System.out.println();
}
完整代码可点击此处进行获取。