这是布置的 AI 作业,今天有同学用奇怪的“旋转法”做了出来,虽然结果应该不是最优解,不过其思维方式还是很新颖的。课本上有广度优先的介绍,广先的好处是,如果有解,必定能够求出最优解!所以先尝试了一下广先算法,算搞定了,下星期可以交差了。
主要思想:
1、判断两个序列的
逆序数的奇偶性是否相同,不同肯定无解,相同就有解。
2、用一个 Queue 存储需要扩展的节点,各用一个 SortList (或者数组、ArrayList、Hasttable等)存储 ClosedList、父节点表(FatherList)、每个状态(节点)对应序列。
3、Queue 开始只有state1,然后出队,进入ClosedList,判断是否可扩展,扩展后的子节点不能与辈份大的节点(父亲、父亲的父亲...)重复。子节点放入 Queue 。
4、只要 Queue 不空,就做循环来找,直到找到一个子节点的序列与 state1 相等,找到后,根据父节点表找到最短路径即可。
C#代码(代码很乱 -__-):
using System;
using System.Text;
using System.Collections;
namespace BlockSimple
{
class App
{
enum MovieDirection
{
None,
Up,
Left,
Right,
Down
}
static void Main(string[] args)
{
Start:
int[,] A=new int[3,3]{{2,8,3},{1,0,4},{7,6,5}};//{{2,8,3},{1,6,4},{7,0,5}}
int[,] B=new int[3,3]{{1,2,3},{8,0,4},{7,6,5}};//{{1,2,3},{8,0,4},{7,6,5}}
string stringA=string.Empty;
string stringB=string.Empty;
int Anxs=0;
int Bnxs=0;
Console.WriteLine("Input A:(a1=283104765,a2=283164705)");
stringA=Console.ReadLine();
if (stringA=="a1")
{
stringA="283104765";
}
if (stringA=="a2")
{
stringA="283164705";
}
Console.WriteLine("Input B:(b=123804765)");
stringB=Console.ReadLine();
if (stringB=="b")
{
stringB="123804765";
}
if (stringA.Length!=9 || stringB.Length!=9)
{
Console.WriteLine("Error! Do it again
");
goto Start;
}
A=ConvertToAry(stringA);
B=ConvertToAry(stringB);
Console.WriteLine("A");
PrintArray(A);
Console.WriteLine("B");
PrintArray(B);
//逆序数
Anxs=GetNiXuShu(A);
Bnxs=GetNiXuShu(B);
Console.WriteLine("------");
Console.WriteLine("A 的逆序数 = "+Anxs.ToString());
Console.WriteLine("B 的逆序数 = "+Bnxs.ToString());
if (System.Math.Abs(Anxs-Bnxs) % 2 !=0)
{
Console.WriteLine("逆序数的奇偶性不同,无解!\r\n");
goto Start;
}
else
{
Console.WriteLine("OK,Continue
");
}
Console.WriteLine("------");
Console.WriteLine("广度优先搜索\r\n------");
//广度优先
//System.Collections.SortedList OpenList=new SortedList();
System.Collections.Queue OpenQueue=new Queue();//作为Open表 (int)
System.Collections.SortedList ClosedList=new SortedList();//作为Closed表 (int,int)
System.Collections.Hashtable FatherList=new Hashtable();//存储父节点 (int,int)
System.Collections.Hashtable StateList=new Hashtable();//key=状态代码,value=状态序列 (int,string)
//初始化
int StateCount=1;//状态计数
//OpenList.Add(StateCount,0);
StateList.Add(1,ConvertToString(A));
OpenQueue.Enqueue(1);
FatherList.Add(1,0);//第一个节点的父亲为0
int LastStateCount=0;//最后一个状态计数,根据此来通过找出父亲节点,推出最短路径
bool IsFind=false;
Console.WriteLine("state1:"+StateList[1]+"\tFather:Null");
while (OpenQueue.Count>0 && IsFind==false)
{
//OpenList --> ClosedList
int CurStateCount=(int)OpenQueue.Dequeue();
ClosedList.Add(CurStateCount,(int)FatherList[CurStateCount]);//ClosedList好像没有必要加入 父亲节点
if ((string)StateList[CurStateCount]==stringB)
{
LastStateCount=CurStateCount;
break;
}
else
{
//是否可扩展?扩展后将子节点放入OpenList的尾部
//扩展,找到元素0的位置,查看0是否可以上下左右移动,移动后的结果作为子节点(不能与起父节点的序列相同)
string CurA=(string)StateList[CurStateCount];
MovieDirection[] MD=new MovieDirection[]{MovieDirection.Left,MovieDirection.Up,MovieDirection.Right,MovieDirection.Down};
for (int i=0;i<4;i++)
{
if (IsFind)
{
break;
}
string newMovie=TryMovie(CurA,MD[i]);
//Console.WriteLine(CurA+"-->"+CurStateCount.ToString()+(string)StateList[CurStateCount]);
if (newMovie!="")
{
//并且不能=父亲、父亲的父亲

bool IsEqueFather=false;
int father=CurStateCount;
while (father!=0)
{
if (newMovie==(string)StateList[father])
{
IsEqueFather=true;
}
father=Convert.ToInt32(FatherList[father]);
}
if (IsEqueFather==false)
{
//加入到OpenQueue里面
StateCount++;
OpenQueue.Enqueue((object)StateCount);
FatherList.Add(StateCount,CurStateCount);
StateList.Add(StateCount,newMovie);
Console.WriteLine("state"+StateCount.ToString()+":"+newMovie+"\tFather:"+FatherList[StateCount].ToString()+"");
System.Threading.Thread.Sleep(10);
//判断
//Console.WriteLine((string)StateList[StateCount]+"=?"+stringB);
if ((string)StateList[StateCount]==stringB)
{
LastStateCount=StateCount;
IsFind=true;
}
}
}
}
}
}
Console.WriteLine("------\r\nFind!state"+LastStateCount.ToString()+"=B\r\n");
//找到路径
int f=LastStateCount;
string Path=string.Empty;
ArrayList p=new ArrayList();
while (f!=0)
{
Path=f.ToString()+"->"+Path;
p.Add(f);
f=Convert.ToInt32(FatherList[f]);
}
Console.WriteLine("解的路径为: "+Path.Substring(0,Path.Length-2));
p.Reverse();
for (int i=0;i<p.Count;i++)
{
Console.WriteLine("state"+p[i].ToString()+":"+StateList[p[i]]);
PrintArray(ConvertToAry((string)StateList[p[i]]));
}
Console.WriteLine("\r\n----------------------------\r\nTest Again?Input Y
");
string Test=string.Empty;
Test=Console.ReadLine();
if (Test.ToLower()=="y")
{
goto Start;
}
}
//打印矩阵
private static void PrintArray(int[,] X)
{
for (int i=0;i<3;i++)
{
for (int j=0;j<3;j++)
{
Console.Write(X[i,j].ToString()+",");
}
Console.Write("\r\n");
}
}
//移动0,如果可移,返回移动后的序列,若不可以,返回空
private static string TryMovie(string XuLie,MovieDirection D)
{
int[,] X=new int[3,3];
X=ConvertToAry(XuLie);
//参数不应该是数组,因为数组是引用变量
//找到0的位置
int iZero=-1;
int jZero=-1;
for (int i=0;i<3;i++)
{
for (int j=0;j<3;j++)
{
if (X[i,j]==0)
{
iZero=i;
jZero=j;
}
}
}
if (D==MovieDirection.Left)
{
if (jZero>0)
{
X[iZero,jZero]=X[iZero,jZero-1];
X[iZero,jZero-1]=0;
return ConvertToString(X);
}
}
if (D==MovieDirection.Up)
{
if (iZero>0)
{
X[iZero,jZero]=X[iZero-1,jZero];
X[iZero-1,jZero]=0;
return ConvertToString(X);
}
}
if (D==MovieDirection.Right)
{
if (jZero<2)
{
X[iZero,jZero]=X[iZero,jZero+1];
X[iZero,jZero+1]=0;
return ConvertToString(X);
}
}
if (D==MovieDirection.Down)
{
if (iZero<2)
{
X[iZero,jZero]=X[iZero+1,jZero];
X[iZero+1,jZero]=0;
return ConvertToString(X);
}
}
return "";
}
//数组转化成为序列
private static string ConvertToString(int[,] X)
{
string rtn=string.Empty;
for (int i=0;i<3;i++)
{
for (int j=0;j<3;j++)
{
rtn+=X[i,j].ToString();
}
}
return rtn;
}
//序列转化称数组
private static int[,] ConvertToAry(string str)
{
int[,] X=new int[3,3];
X[0,0]=Convert.ToInt32(str.Substring(0,1));
X[0,1]=Convert.ToInt32(str.Substring(1,1));
X[0,2]=Convert.ToInt32(str.Substring(2,1));
X[1,0]=Convert.ToInt32(str.Substring(3,1));
X[1,1]=Convert.ToInt32(str.Substring(4,1));
X[1,2]=Convert.ToInt32(str.Substring(5,1));
X[2,0]=Convert.ToInt32(str.Substring(6,1));
X[2,1]=Convert.ToInt32(str.Substring(7,1));
X[2,2]=Convert.ToInt32(str.Substring(8,1));
return X;
}
//计算逆序数,忽略0
private static int GetNiXuShu(int[,] X)
{
int m=0;
int n=0;
int[] C=new int[9];
for (int i=0;i<3;i++)
{
for (int j=0;j<3;j++)
{
C[n]=X[i,j];
n++;
}
}
for (int i=0;i<9;i++)
{
for (int j=i+1;j<9;j++)
{
if (C[j]!=0 && C[j]<C[i])
{
m++;
}
}
}
return m;
}
}
}
运行结果:
posted @ 2007-12-04 02:07
卡卡 ^ cacard 阅读(259)
评论(2) 编辑 收藏 所属分类:
算法