DFS解两道逻辑推理题

 

1 有五栋五种颜色的房子 
2 每一位房子的主人国籍都不同 
3 这五个人每人只喝一种饮料,只抽一种牌子的香烟,只养一种宠物 
4 没有人有相同的宠物,抽相同牌子的香烟,喝相同的饮料 
提示: 
1  英国人住在红房子里 
2  瑞典人养了一条狗 
3  丹麦人喝茶 
4  绿房子在白房子左边 
5  绿房子主人喝咖啡 
6  抽PALL MALL烟的人养了一只鸟 
7  黄房子主人抽DUNHILL烟 
8  住在中间那间房子的人喝牛奶 
9  挪威人住第一间房子 
10 抽混合烟的人住在养猫人的旁边 
11 养马人住在抽DUNHILL烟的人旁边 
12 抽BLUE MASTER烟的人喝啤酒 
13 德国人抽PRINCE烟 
14 挪威人住在蓝房子旁边 
15 抽混合烟的人的邻居喝矿泉水 

问题是:谁养鱼???
--------------------- 

5个人来自不同地方,住不同房子,养不同动物,吸不同牌子香烟,喝不同饮料,喜欢不同食物。根据以下线索确定谁是养猫的人。

1. 红房子在蓝房子的右边,白房子的左边(不一定紧邻) 
2. 黄房子的主人来自香港,而且他的房子不在最左边。 
3. 爱吃比萨的人住在爱喝矿泉水的人的隔壁。 
4. 来自北京的人爱喝茅台,住在来自上海的人的隔壁。 
5. 吸希尔顿香烟的人住在养马人的右边隔壁。 
6. 爱喝啤酒的人也爱吃鸡。 
7. 绿房子的人养狗。 
8. 爱吃面条的人住在养蛇人的隔壁。 
9. 来自天津的人的邻居(紧邻)一个爱吃牛肉,另一个来自成都。 
10.养鱼的人住在最右边的房子里。 
11.吸万宝路香烟的人住在吸希尔顿香烟的人和吸“555”香烟的人的中间(紧邻) 
12.红房子的人爱喝茶。 
13.爱喝葡萄酒的人住在爱吃豆腐的人的右边隔壁。 
14.吸红塔山香烟的人既不住在吸健牌香烟的人的隔壁,也不与来自上海的人相邻。 
15.来自上海的人住在左数第二间房子里。 
16.爱喝矿泉水的人住在最中间的房子里。 
17.爱吃面条的人也爱喝葡萄酒。 

18.吸“555”香烟的人比吸希尔顿香烟的人住的靠右 
--------------------- 
程序使用方法:

1、构建数据集data

2、最好构建一个初步推测的结果集,5*5的题目,在有4个值的时候就能有很好的速度提升

3、需要根据题目的条件,抽象为方法构成filter方法中的条件

4、可以回复我更多此类题目进行测试吗

import java.util.HashMap;
import java.util.Map;

public class DFS {

	//数据集
	static String[][] data = new String[][]{
//		{"英","瑞","挪","德","丹"},
//		{"黄","蓝","红","绿","白"},
//		{"马","狗","猫","鸟","鱼"},
//		{"茶","奶","咖","啤","水"},
//		{"DU","PA","HH","PR","BM"},
		{"京","沪","港","津","川"},
		{"蓝","绿","黄","红","白"},
		{"鱼","猫","蛇","狗","马"},
		{"塔","五","万","希","健"},
		{"啤","茶","水","葡","茅"},
		{"鸡","萨","牛","面","豆"},
	};
	//预测结果集
	static String[][] pRes = new String[][]{
		{"京","沪",null,null,null},
		{null,null,null,null,null},
		{null,null,null,null,"鱼"},
		{null,null,null,null,null},
		{"茅",null,"水",null,null},
		{null,null,null,null,null},
//		{"挪",null,"英",null,null},
//		{"黄","蓝","红","绿","白"},
//		{null,"马",null,null,null},
//		{null,null,"奶","咖",null},
//		{"DU",null,null,null,null},
	};
	
	
	static int m = data.length;//结果集的宽度
	static int n = data[0].length;//结果集的高度
	static String[][] res = new String[m][n];//结果集
	static Map<String, Point> resMap = new HashMap<>();//结果集中每个值的坐标位置 

	//剪枝后处理的结果集的数量
	static long Number = 1;
	
	//产生结果集的过滤条件
	static boolean filter(){
		boolean b = (lr("蓝", "红")
				&& lr("红", "白")
				&& tz("港", "黄")
				&& !is(0, "港")
				&& lj("萨", "水")
				&& tz("京", "茅")
				&& lj("沪", "京")
				&& lr("马", "希")
				&& lj("马", "希")
				&& tz("啤", "鸡")
				&& tz("绿", "狗")
				&& lj("面", "蛇")
				&& lj("津", "牛")
				&& lj("津", "川")
				&& !lj("牛", "川")
				&& is(n-1, "鱼")
				&& lr("希", "万")
				&& lj("希", "万")
				&& lr("万", "五")
				&& lj("万", "五")
				&& tz("红", "茶")
				&& lr("豆", "葡")
				&& lj("葡", "豆")
				&& !lj("塔", "健")
				&& !lj("塔", "沪")
				&& is(1, "沪")
				&& is(n/2, "水")
				&& tz("面", "葡"));
//		boolean b = (lr("绿", "白")
//				&& is(n/2, "奶")
//				&& is(0, "挪")
//				&& tz("英", "红")
//				&& tz("瑞", "狗")
//				&& tz("丹", "茶")
//				&& tz("绿", "咖")
//				&& tz("PA", "鸟")
//				&& tz("黄", "DU")
//				&& lj("HH", "猫")
//				&& lj("马", "DU")
//				&& tz("BM", "啤")
//				&& tz("德", "PR")
//				&& lj("挪", "蓝")
//				&& lj("HH", "水"));
		return b;
	}
	
	//判断结果集是否正确
	static boolean getRes(){
		Number++;
		//System.out.println();打印非常耗时
		if(filter()){
			System.out.println("=start======================");
			for(int i = 0;i < m; i++){
				for(int j = 0;j < n; j++){
					System.out.print(res[i][j] + " ");
				}
				System.out.println();
			}
			System.out.println("==end=======================");
			return true;
		}
		return false;
	}
	
	//深度优先搜索
	static void dfs(int x,int y){
		
		for(int j = 0; j < y; j++){
			if(res[x][y] == res[x][j]){
				return;
			}
		}
		if(y != -1){
			resMap.put(res[x][y], new Point(x,y));
		}
		
		if(x >= m-1 && y >= n-1){
			getRes();
		}
		y++;
		if(y >= n){
			x++;
			y=0;
		}
		if(x >= m ){
			return;
		}

		if(pRes[x][y] != null){
			res[x][y]=pRes[x][y];
			dfs(x, y);
			return;
		}
		for(int j = 0;j < n; j++){
			res[x][y] = data[x][j];
			dfs(x, y);
		}
	}
	//第J列有str
	static boolean is(int j, String str){
		boolean b = resMap.get(str).y == j;
		return b;
	}
	
	//同宗: 第J列有str1且第J列有str2
	static boolean tz(String str1, String str2){
//		boolean b = resMap.get(str1).y == resMap.get(str2).y;
		return w(str1,str2) == 0;
	}
	//邻居:第J列有str1且他的邻居有str2
	static boolean lj(String str1, String str2){
//		boolean b = Math.abs(resMap.get(str1).y - resMap.get(str2).y) == 1;
		return Math.abs(w(str1,str2)) == 1;
	}
	
	//如果str1在str2左边 返回true;
	static boolean lr(String str1, String str2){
//		boolean b = resMap.get(str1).y < resMap.get(str2).y;
		return w(str1,str2) < 0;
	}
	static int w(String str1, String str2){
		return resMap.get(str1).y - resMap.get(str2).y;
	}
	static boolean in(String str1, String str2, String str3){
		return (lr(str1, str2)&&lr(str2, str3)||lr(str3, str2)&&lr(str2, str1));
	}
	
	static final int O_TZ = 1;//同宗
	static final int O_LJ = 2;//邻居
	static final int O_LR = 3;//左邻居
	static final int O_RL = 4;//右邻居
	static final int O_IL = 5;//在左边
	static final int O_IR = 6;//在右边
	
	static boolean cp(String str1, String str2, int o){
		boolean b = false;
		int w = w(str1,str2);
		switch (o) {
		case O_TZ:
			b = w == 0;
			break;
		case O_LJ:
			b = Math.abs(w) == 1;
			break;
		case O_LR:
			b = w == -1;
			break;
		case O_RL:
			b = w == 1;
			break;
		case O_IL:
			b = w < 0;
			break;
		case O_IR:
			b = w > 0;
			break;
		default:
			break;
		}
		return b;
	}
	
	static class Point{
		int x;
		int y;
		public Point(int x, int y) {
			this.x = x;
			this.y = y;
		}
		@Override
		public String toString() {
			return x + "," + y;
		}
		
	}
	static boolean over = false;
	
	public static void main(String[] args) {
		
		long startTime = System.currentTimeMillis();
		Thread timer = new Thread(new Runnable() {
			
			@Override
			public void run() {
				try {
					int num = 1;
					while(true){
						Thread.sleep(200);
						if(over){
							break;
						} else if(num++ % 25 == 0){
							System.out.printf("%sms(%s)\n",(System.currentTimeMillis() - startTime), Number);
						}
					}
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		});
		timer.start();
		dfs(0, -1);
		System.out.printf("USE TIME:%sms \n", (System.currentTimeMillis() - startTime));
		over = true;
	}
	
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值