• 博客园logo
  • 会员
  • 周边
  • 众包
  • 新闻
  • 博问
  • 闪存
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录

  • 联系
  • 订阅
  • 管理

View Post

sicily 1150 简单魔板 & 1151 魔板 bfs

典型的bfs, 第一个是自己写的没有做任何优化,需要8^8的空间保存状态
后来看了别人解题报告,学会了康托展开,全排列压缩,只需要8!空间
 
#include <iostream>
#include <string>
#include <queue>
#include <memory.h>
using namespace std;

struct my_status
{
	int a[2][4];
	string path;

	my_status(){}

	my_status(int a[2][4])
	{
		for (int i = 0; i < 2; i++)
			for (int j = 0; j < 4; j++)
				this->a[i][j] = a[i][j];
		path = "";
	}

	my_status& operator=(const my_status& item)
	{
		for (int i = 0; i < 2; i++)
			for (int j = 0; j < 4; j++)
				a[i][j] = item.a[i][j];
		path = item.path;
		return *this;
	}

	bool operator== (const my_status& item)
	{
		for (int i = 0; i < 2; i++)
			for (int j = 0; j < 4; j++)
				if (a[i][j] != item.a[i][j])
					return false;

		return true;
	}
};

bool isvisit[8][8][8][8][8][8][8][8];
int max_step;
int goal_status[2][4];
int inite_statue[2][4] = {{1,2,3,4}, {8,7,6,5}};

my_status do_operate(int, const my_status&);

void bfs();

int main()
{
	while (cin >> max_step && max_step != -1)
	{
		memset(isvisit, false, sizeof(isvisit));

		for (int i = 0; i < 2; i++)
			for (int j = 0; j < 4; j++)
				cin >> goal_status[i][j];
		bfs();
	}
	return 0;
}

void bfs()
{
	my_status p,next_status;

	queue<my_status> Q;
	char c;
	Q.push(inite_statue);

	while (!Q.empty())
	{
		p = Q.front();
		Q.pop();

		if (p.path.size() > max_step)
		{
			cout << "-1" << endl;
			return;
		}
		if (p == goal_status)
		{
			cout << p.path.size() << " " << p.path << endl;
			return;
		}

		for (int i = 0; i < 3; i++)
		{
			next_status = do_operate(i, p);
			c = 'A'+i;
			next_status.path = p.path + c;

			if (!isvisit[next_status.a[0][0]-1][next_status.a[0][1]-1][next_status.a[0][2]-1][next_status.a[0][3]-1][next_status.a[1][0]-1][next_status.a[1][1]-1][next_status.a[1][2]-1][next_status.a[1][3]-1])
			{
				isvisit[next_status.a[0][0]-1][next_status.a[0][1]-1][next_status.a[0][2]-1][next_status.a[0][3]-1][next_status.a[1][0]-1][next_status.a[1][1]-1][next_status.a[1][2]-1][next_status.a[1][3]-1] = true;
				Q.push(next_status);
			}
		}

	}
}

my_status do_operate(int mode, const my_status& p)
{
	my_status tmp;
	switch (mode)
	{
	case 0:
		for (int i = 0; i < 4; i++)
		{
			tmp.a[0][i] = p.a[1][i];
			tmp.a[1][i] = p.a[0][i];
		}		
		break;
	case 1:
		for (int i = 1; i < 4; i++)
		{
			tmp.a[0][i] = p.a[0][i-1];
			tmp.a[1][i] = p.a[1][i-1];
		}
		tmp.a[0][0] = p.a[0][3];
		tmp.a[1][0] = p.a[1][3];
		break;
	case 2:
		tmp = p;
		tmp.a[0][1] = p.a[1][1];
		tmp.a[0][2] = p.a[0][1];
		tmp.a[1][1] = p.a[1][2];
		tmp.a[1][2] = p.a[0][2];
		break;
	}

	return tmp;
}
 
康托展开
#include <iostream>
#include <string>
#include <queue>
#include <memory.h>
using namespace std;

struct my_status
{
	int a;
	string path;
};

int fact[] = {1, 1, 2, 6, 24, 120, 720, 5040, 40320}; //8!的阶乘表

bool isvisit[50000];
int max_step;
int goal_status;
int inite_statue = 12348765;
int do_operate(int, int);

//康托状态压缩
//把需要8^8的储存空间压缩成只需8!空间
//只有8!有效
int encode(int n)
{
	int tmp[8];
	int cnt, sum;
	
	for (int i = 7; i >= 0; i--)
	{
		tmp[i] = n%10;
		n /= 10;
	}

	for (int i = 0; i < 7; i++)
	{
		cnt = 0;
		
		for (int j = i+1; j < 8; j++)
			if (tmp[i] > tmp[j]) cnt++;

		n += fact[8-i-1] * cnt;
	}
	return n;
}

void bfs();

int main()
{
	int tmp[8];
	
	while (cin >> max_step && max_step != -1)
	{
		memset(isvisit, false, sizeof(isvisit));

		for (int i = 0; i < 8; i++)
			cin >> tmp[i];

		goal_status = tmp[0]*1e7 +tmp[1]*1e6 + tmp[2]*1e5 + tmp[3]*1e4 + tmp[4]*1e3 + tmp[5]*1e2 + tmp[6]*1e1 + tmp[7];
		bfs();
	}
	return 0;
}

void bfs()
{
	my_status p,next_status;
	p.a = inite_statue;
	p.path = "";
	queue<my_status> Q;
	char c;
	Q.push(p);

	while (!Q.empty())
	{
		p = Q.front();
		Q.pop();

		if (p.path.size() > max_step)
		{
			cout << "-1" << endl;
			return;
		}
		if (p.a == goal_status)
		{
			cout << p.path.size() << " " << p.path << endl;
			return;
		}

		for (int i = 0; i < 3; i++)
		{
			next_status.a = do_operate(i, p.a);
			c = 'A'+i;
			next_status.path = p.path + c;

			if (!isvisit[encode(next_status.a)])
			{
				isvisit[encode(next_status.a)] = true;
				Q.push(next_status);
			}
		}

	}
}

int do_operate(int mode, int number)
{
	int tmp = number;
	switch (mode)
	{
	case 0: //操作A,上下行交换
		tmp = number/1000%10*1e7 + number/100%10*1e6 + number/10%10*1e5 + number%10*1e4 + number/(10000000)%10*1e3 + number/1000000%10*1e2 + number/100000%10*10 + number/10000%10;
		break;
	case 1: //操作B,每行向后移动一位
		tmp = number/10000%10*1e7 + number/10000000%10*1e6 + number/1000000%10*1e5 + number/100000%10*1e4 + number%10*1e3 + number/1000%10*1e2 + number/100%10*10 +number/10%10;
		break;
	case 2: //操作C,旋转
		tmp = number/10000000%10*1e7 + number/100%10*1e6 + number/1000000%10*1e5 + number/10000%10*1e4 + number/1000%10*1e3 + number/10%10*1e2 + number/100000%10*10 + number%10;
		break;
	}
	return tmp;
}

posted on 2010-11-28 23:42  sysuwhj  阅读(3460)  评论(0)    收藏  举报

刷新页面返回顶部
 
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3