农场里有兔子和鸡若干只,知道共20个头和56条腿。问兔子和鸡各多少只?
我记得以前小学或是初中的时候经常要解类似这样的问题
一般我们的想法是:
设有 X 只鸡 Y只免子
X+Y=20;
x*2 +Y*4 =56;
解方程组我们就可以得到这个问题的解了.
如果让我们要程序的思想来解这个问题。。 我们一般会写成
for(int i=1;i<=20;i++)
{
for(int j=1;j<20;j++)
{
if (i+j==20&i*2+j*4==56)
{
// Save i and j;
}
}
}
以前解决这种问题的时候。我们得到的思想都是利用计算机强大的计算能力去穷举所有的可能值
难道计算机就不能按照人的这种思路 方程组。 或一定的推理过程去解决这种问题?
今天我们就来看NSlove的一个类库。专门用来解决这种有限定条件的问题:
看代码(注下载下来的下载下来Nslover类库的三个dll都需引用)
using System;
/**
* Rabbits and pheasants problem. 20 heads and 56 legs.
* How many rabbits and how many pheasants?
*/
public class Rabbit : Solver {
public void Run() {
// maximum 20 rabbits/pheasants
Var rabbits = var(0, 20, "Rabbits");
Var pheasants = var(0, 20, "Pheasants");
// Total 20 heads
Post(rabbits.Sum(pheasants).Eq(20));
// Total 56 legs
Post(rabbits.Prod(4).Sum(pheasants.Prod(2)).Eq(56));
Console.WriteLine(rabbits+" "+pheasants);
}
public static void Main() {
(new Rabbit()).Run();
}
}
/* result
Rabbits[8]
Pheasants[12]
*/
其实它是可以解决这一类的问题:
Scheduling problems
Allocation problems
Timetabling problems
Optimization problems
内部流程应该是按照一定的推理过程来实现的
NSlover作者http://www.cs.cityu.edu.hk/~hwchun/nsolver/
另一个人写的解决爱因斯坦智力题
1、在一条街上,有5座房子,喷了5种颜色。
2、每个房里住着不同国籍的人
3、每个人喝不同的饮料,抽不同品牌的香烟,养不同的宠物
问题是:谁养鱼?
提示:
1、英国人住红色房子
2、瑞典人养狗
3、丹麦人喝茶
4、绿色房子在白色房子左面
5、绿色房子主人喝咖啡
6、抽Pall Mall 香烟的人养鸟
7、黄色房子主人抽Dunhill 香烟
8、住在中间房子的人喝牛奶
9、 挪威人住第一间房
10、抽Blends香烟的人住在养猫的人隔壁
11、养马的人住抽Dunhill 香烟的人隔壁
12、抽Blue Master的人喝啤酒
13、德国人抽Prince香烟
14、挪威人住蓝色房子隔壁
15、抽Blends香烟的人有一个喝水的邻居
在数学中。不懂得如何去表达,左边这种逻辑关系,隔壁这种关系, 用画图的话可以容易解出
计算机穷举方法 http://www.pconline.com.cn/pcedu/empolder/net/cs/0509/acc/05-09-21-e-2.txt
NSlover 的方法 http://arch.pconline.com.cn/pcedu/empolder/net/cs/0509/acc/05-09-21-e-4.txt
using System.Text;
using ai.net.Solver;
using System.Diagnostics;
using System.Collections;
class Einstein : Solver
{
public void Run()
{
// the 房子s
Var 红房子 = var(0, 4, "红房子");
Var 绿房子 = var(0, 4, "绿房子");
Var 白房子 = var(0, 4, "白房子");
Var 黄房子 = var(0, 4, "黄房子");
Var 蓝房子 = var(0, 4, "蓝房子");
VarList all房子s = varList(红房子, 绿房子, 白房子, 黄房子, 蓝房子);
// nationalities
Var 英国人 = var(0, 4, "英国人");
Var 瑞典人 = var(0, 4, "瑞典人");
Var 丹麦人 = var(0, 4, "丹麦人");
Var 挪威人 = var(0, 4, "挪威人");
Var 德国人 = var(0, 4, "德国人");
VarList allNationalities = varList(英国人, 瑞典人, 丹麦人, 挪威人, 德国人);
// beverages
Var 茶 = var(0, 4, "茶");
Var 咖啡 = var(0, 4, "咖啡");
Var 牛奶 = var(0, 4, "牛奶");
Var 啤酒 = var(0, 4, "啤酒");
Var 矿泉水 = var(0, 4, "矿泉水");
VarList allBeverages = varList(茶, 咖啡, 牛奶, 啤酒, 矿泉水);
// cigarettes
Var pallMall = var(0, 4, "Pall Mall");
Var dunhill = var(0, 4, "Dunhill");
Var 混合烟 = var(0, 4, "混合烟");
Var BlueMasters = var(0, 4, "BlueMasters");
Var Prince = var(0, 4, "Prince");
VarList allCigs = varList(pallMall, dunhill, 混合烟, BlueMasters, Prince);
// pets
Var 狗 = var(0, 4, "狗");
Var 鸟 = var(0, 4, "鸟");
Var 鱼 = var(0, 4, "鱼");// <-- Who owns the 鱼?
Var 马 = var(0, 4, "马");
Var 猫 = var(0, 4, "猫");
VarList allPets = varList(狗, 鸟, 鱼, 马, 猫);
// More clues
Post(红房子.Eq(英国人));
Post(狗.Eq(瑞典人));
Post(茶.Eq(丹麦人));
//The 绿 房子 is on the left of the 白 房子
Var gLeft = 白房子.Diff(绿房子);
gLeft.SetRange(0, 1);
Post(gLeft.Neq(0));
Post(绿房子.Eq(咖啡));
Post(pallMall.Eq(鸟));
Post(黄房子.Eq(dunhill));
Post(牛奶.Eq(2));
Post(挪威人.Eq(0));
Var 混合烟Vs鱼 = 鱼.Diff(混合烟);
混合烟Vs鱼.SetRange(-1, 1);
Post(混合烟Vs鱼.Neq(0));
Var 马VsDunhill = 马.Diff(dunhill);
马VsDunhill.SetRange(-1, 1);
Post(马VsDunhill.Neq(0));
Post(BlueMasters.Eq(啤酒));
Post(Prince.Eq(德国人));
Var 蓝Vs挪威人 = 蓝房子.Diff(挪威人);
蓝Vs挪威人.SetRange(-1, 1);
Post(蓝Vs挪威人.Neq(0));
Var 混合烟Vs矿泉水 = 混合烟.Diff(矿泉水);
混合烟Vs矿泉水.SetRange(-1, 1);
Post(混合烟Vs矿泉水.Neq(0));
Post(AllDiff(all房子s));
Post(AllDiff(allNationalities));
Post(AllDiff(allBeverages));
Post(AllDiff(allCigs));
Post(AllDiff(allPets));
Activate(all房子s);
Activate(allNationalities);
Activate(allBeverages);
Activate(allCigs);
Activate(allPets);
while (NextSolution())
{
Console.WriteLine(allNationalities);
Console.WriteLine(all房子s);
Console.WriteLine(allBeverages);
Console.WriteLine(allCigs);
Console.WriteLine(allPets);
}
}
public static void Main()
{
Einstein solver = new Einstein();
solver.Run();
}
}