POJ-2965-The Pilots Brothers' refrigerator

此题搞了个双向BFS以为能快点,不过效果似乎不太理想。
用mask与原状态进行异或得到下一个状态是关键。
用STL的话G++超时,C++过。
自己写队列的话都能过。
双向队列要注意每一次扩展时要记录下子代的个数,下一次搜索要将子代搜索完了才算完成一次扩展。
/*
ID:slowlight
PROG:
LANG:C++
DATE:
*/
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <queue>

using namespace std;

typedef struct{
	int x;
	int y;
	int state;
	int step;
}LastStep;

const int MAXSIZE = ( 1 << 16 ) + 1;

const int mask[16] = {63624, 62532, 61986, 61713, 36744, 20292, 12066, 7953, 35064, 17652, 8946, 4593, 34959, 17487, 8751, 4383}; 

bool vis1[MAXSIZE];
bool vis2[MAXSIZE];

LastStep lastStep1[MAXSIZE];
LastStep lastStep2[MAXSIZE];


void print( int state , int init_state )
{
	if( state == init_state )
	{
		return;
	}
	else
	{
		print( lastStep1[state].state, init_state );
		
		printf("%d %d\n", lastStep1[state].x + 1, lastStep1[state].y + 1);
	}
}


int main()
{
	freopen("input.in", "r", stdin);
	freopen("output.out", "w", stdout);
	
	/*init*/
	int i, j, k;
	int temp;
	int init_state;
	int x, y;
	char c;
	
	queue< int > que1;
	queue< int > que2;
	
	init_state = 0;
	
	/*input*/
	for(i=0;i<4;i++)
	{
		for(j=0;j<4;j++)
		{
			scanf("%c", &c);
			
			if( c == '+' )
			{
				init_state += ( 1 << ( 15 - ( i * 4 + j ) ) );
			}
		}
		
		getchar();
	}
	
	/*BFS*/
	vis1[init_state] = true;
	vis2[0] = true;
	
	for(i=0;i<=MAXSIZE;i++)
	{
		lastStep1[i].state = 0;
		lastStep1[i].step = 0;
		lastStep1[i].x = 0;
		lastStep1[i].y = 0;
		
		lastStep2[i].state = 0;
		lastStep2[i].step = 0;
		lastStep2[i].x = 0;
		lastStep2[i].y = 0;
		
	}
	
	
	que1.push(init_state);
	que2.push(0);
	
	int L1 = 1;
	int L2 = 1;
	int cnt1;
	int cnt2;
	
	while( !que1.empty() || !que2.empty() )
	{
		int front1;
		int front2;
		
		if( que1.size() <= que2.size() )
		{
			
			/*que1*/
			cnt1 = 0;
			
			if( !L1 )
				L1 = 1;
			
			while( L1 )
			{
				if( !que1.empty() )
				{
					
					
					front1 = que1.front();
					
					que1.pop();
					
					if( vis2[front1] )
					{
						temp = front1;
						
						break;
					}
					
					for(i=0;i<16;i++)
					{
						
						x = i / 4;
						y = i % 4;
						
						k = front1 ^ mask[i];
						if( !vis1[k] )
						{
							vis1[k] = true;
							
							que1.push( k );
							
							lastStep1[k].x = x;
							
							lastStep1[k].y = y;
							
							lastStep1[k].state = front1;
							
							lastStep1[k].step = lastStep1[front1].step + 1;
							
							cnt1++;
						}
					}
					
					L1--;
				}
			}
			if( L1 )
			{
				break;
			}
			L1 = cnt1;
			
		}
		else	
		{
			
			cnt2 = 0;
			
			if( !L2 )
				L2 = 1;
			/*que2*/
			while( L2 )
			{
				if( !que2.empty() )
				{
					front2 = que2.front();
					
					que2.pop();
					
					if( vis1[front2] )
					{
						temp = front2;
						
						break;
					}
					
					for(i=0;i<16;i++)
					{
						
						x = i / 4;
						y = i % 4;
						
						k = front2 ^ mask[i];
						if( !vis2[k] )
						{
							vis2[k] = true;
							
							que2.push( k );
							
							lastStep2[k].x = x;
							
							lastStep2[k].y = y;
							
							lastStep2[k].state = front2;
							
							lastStep2[k].step = lastStep2[front2].step + 1;
							
							cnt2++;
						}
					}
					L2--;
				}
			}
			
			if( L2 )
				break;
			
			L2 = cnt2;
		}
	}
	
	printf("%d\n", lastStep1[temp].step + lastStep2[temp].step);
	
	print(temp, init_state);
	
	while( temp )
	{
		printf("%d %d\n", lastStep2[temp].x + 1, lastStep2[temp].y + 1);
		
		temp = lastStep2[temp].state;
	}
	
	return 0;
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值