人工智能 - 马少平 - 朱小燕 - 编著 - 清华大学出版社
P55 第一章 习题1.2
积木原始状态 BBBWWWE 其中 E 表示空格,W表示白块,B表示黑块。
题目要求将所有白块都处于黑块的左侧,空格块可任意位置。
建模:将B看成1,将W看成0,而E看成-1,检测是否满足条件时,将-1除开,要求序列非递减。
对于滑动积木的状态记录问题思考:
记录方法:
1. 七维数组记录, record[3][3][3][3][3][3][3]; 空间3^7 = 2187 有再多黑白块或空格,这种方法不适用。
注:此时将B看成2,W可看成1,E看成0,为了能直接在数组中引用。
2. map键值映射,map<string,bool>。
3. vector、set导入,vecotr<string>, set<string>,检查子集判断是否存在过状态。
4. 将B,W映射成不同的数值,如BBBWWW -> 654321,将各个值计算后,进行比较得出是否存在。空间 7! = 5040。
获得解值(极粗糙版):
#include"SlideBlockGame.h"
#include<iostream>
#include<cstdio>
using namespace std;
//To record the arising block' status.
int record_status[3][3][3][3][3][3][3];
//To record success
int flag;
//Copy the block
void copy(int temp_block[], int b[])
{
for (int i = 0;i < 7;++i)
temp_block[i] = b[i];
}
//Display the block'status.
void showVarystatus(int block[])
{
for (int i = 0;i < 7;++i)
cout << block[i] << ' ';
cout << endl;
}
//Judge the block'status whether satisfying the goal or not.
bool isGoalstatus(int block[])
{
int numi = 0,numj;
for (int i = 0;i < 4;++i)
{
numj = 0;
if (block[i] == 1)
{
numi++;
for (int j = i + 1;j < 7;++j)
if (block[j] == 2)
numj++;
if (numj < 3)
return false;
}
}
if (numi == 3)
{
flag = 1;
cout << "satisfy.....";
showVarystatus(block);
return true;
}
return false;
}
void modifystatus(int b[],int able_shift)
{
if (flag)
return;
/*
isGoalstatus had return a result: false
if (isGoalstatus(b) || flag)
return true;
*/
isGoalstatus(b);
if (flag) //success
return;
if (record_status[b[0]][b[1]][b[2]][b[3]][b[4]][b[5]][b[6]]) //this status had arisen
return;
showVarystatus(b);
int index[6] = { -3,-2,-1,+1,+2,+3 }; //modify factors
record_status[b[0]][b[1]][b[2]][b[3]][b[4]][b[5]][b[6]] = 1; //make a record
for (int i = 0;i < 6;++i)
{
int temp = able_shift + index[i];
if (temp <= 6 && temp >= 0)
{
//has to create a new array
int temp_block[7];
copy(temp_block, b);
//exchange the locations.
int s = temp_block[temp];
temp_block[temp] = 0;
temp_block[able_shift] = s;
modifystatus(temp_block, temp);
}
}
}
int main()
{
int block[7] = { 2,2,2,1,1,1,0 }; //Initial status.
memset(record_status,0,sizeof(record_status));
flag = 0;
modifystatus(block, 6); //Modify the block'status to satisfy the goal.
if(flag)
cout << "satisfy the rule" << endl;
system("pause");
}
其中isGoalStatue(),错误想法
1.前四个位置有出现过3个1即可,错误:1121022
2.数列非递减,错误:1220112,1122201,由于空格(0)存在,特判后失败。
最后实现isGoalStatue:
检查到每一个白格,检查其后是否存在3个黑格。
深搜路径版
#include"SlideBlockGame.h"
#include<iostream>
#include<cstdio>
using namespace std;
//To record the arising block' Status.
int record_status[3][3][3][3][3][3][3];
//To record success
int flag;
//Copy the block
void copy(int temp_block[], int b[])
{
for (int i = 0;i < 7;++i)
temp_block[i] = b[i];
}
//Display the block'Status.
void showVaryStatus(blockstatus* block)
{
/*
for (int i = 0;i < 7;++i)
cout << block->blocks[i] << ' ';
cout << endl;
*/
blockstatus* pre1, *pre2;
pre1 = block->link_pre_node;
pre2 = pre1->link_pre_node;
block->link_pre_node = NULL;
while (pre2)
{
pre1->link_pre_node = block;
block = pre1;
pre1 = pre2;
pre2 = pre2->link_pre_node;
}
pre1->link_pre_node = block;
// pre2->link_pre_node = pre1;
while (pre1)
{
for (int i = 0;i < 7;++i)
cout << pre1->blocks[i] << ' ';
cout << endl;
pre1 = pre1->link_pre_node;
}
}
//Judge the block'Status whether satisfying the goal or not.
bool isGoalStatus(blockstatus* block)
{
int b[7];
copy(b, block->blocks);
int num;
for (int i = 0;i < 7;++i)
{
num = 0;
if (b[i] == 1)
{
for (int j = i + 1;j < 7;++j)
if (b[j] == 2)
num++;
if (num < 3)
return false;
}
}
flag = 1;
cout << "satisfy....."<<endl;
showVaryStatus(block);
return true;
}
void modifyStatus(blockstatus* fatherblock,int able_shift)
{
if (flag)
return;
/*
isGoalStatus had return a result: false
if (isGoalStatus(b) || flag)
return true;
*/
isGoalStatus(fatherblock);
if (flag) //success
return;
int b[7];
copy(b, fatherblock->blocks);
if (record_status[b[0]][b[1]][b[2]][b[3]][b[4]][b[5]][b[6]]) //this Status had arisen
return;
int index[6] = { -3,-2,-1,+1,+2,+3 }; //modify factors
record_status[b[0]][b[1]][b[2]][b[3]][b[4]][b[5]][b[6]] = 1; //make a record
for (int i = 0;i < 6;++i)
{
int new_shift = able_shift + index[i];
if (new_shift <= 6 && new_shift >= 0)
{
//has to create a new blockstatus
blockstatus* newblock;
newblock = new blockstatus;
copy(newblock->blocks, b);
//exchange the locations.
int s = newblock->blocks[new_shift];
newblock->blocks[new_shift] = 0;
newblock->blocks[able_shift] = s;
newblock->link_pre_node = fatherblock;
modifyStatus(newblock, new_shift);
}
}
}
void initBlockStatus(blockstatus* block)
{
for (int i = 0;i < 3;++i)
block->blocks[i] = 2;
for (int i = 3;i < 6;++i)
block->blocks[i] = 1;
block->blocks[6] = 0;
block->link_pre_node = NULL;
}
int main()
{
blockstatus* block;
block = new blockstatus; //Initial Status.
initBlockStatus(block);
/*
for (int i = 0;i < 7;++i)
cout << block->blocks[i] << ' ';
cout << endl;
*/
memset(record_status,0,sizeof(record_status));
flag = 0;
modifyStatus(block, 6); //Modify the block'Status to satisfy the goal.
if(flag)
cout << "satisfy the rule" << endl;
system("pause");
}