状态记录

本文探讨了如何记录和解决积木滑动问题,其中目标是将所有白块置于黑块左侧,空格位置不限。提出了四种状态记录方法:七维数组、映射键值、vector和set导入以及数值映射。在实现解决方案的过程中,重点介绍了如何判断是否达到目标状态,即检查每个白块后面是否有至少三个黑块。文章指出,初始的判断条件如仅看前四个位置的黑块数量或序列非递减并不充分,需考虑空格的影响,最终实现了一个精确的isGoalStatue函数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

人工智能 - 马少平 - 朱小燕 - 编著 - 清华大学出版社


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");
}





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值