uva 321 - The New Villa

隐式图搜索,需将所有房间亮着的灯和当前位置的整体的状态抽象为图中的一个节点,进行搜索

#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
#define MAX_SIZE 10000
#define MOV	1
#define ON  2
#define OFF	3
typedef struct _node
{
	int room;
	int parent;
	int dist;
	int oper;
	int to;
	int state[12];
}Node;
int		goal[12];
int		r,d,s;
char	G[20][20];
char	control[20][20];	
Node	q[MAX_SIZE];
int		head[MAX_SIZE],next[MAX_SIZE];
void input()
{
	int x,i,j;
	memset(G, 0, sizeof(G));
	memset(control,0,sizeof(control));
	memset(q,0,sizeof(q));
	memset(goal,0,sizeof(goal));
	memset(head,0,sizeof(head));
	memset(next,0,sizeof(next));
	for(x=0; x<d; x++)
	{
		scanf("%d %d",&i, &j);
		G[i][j]	= 1;
		G[j][i] = 1;
	}
	for(x=0; x<s; x++)
	{
		scanf("%d %d",&i, &j);
		control[i][j] = 1;
	}
	goal[r]	= 1;
}
#define HASH	10240
int hash(int arr[])
{
	int x=0;
	for(int i=1; i<=10; i++)
		x = (x<<1) | arr[i];
	return x%HASH;
}
int try_insert(int rear)
{
	int h = hash(q[rear].state);
	int u = head[h];
	while(u)
	{
		if(memcmp(q[rear].state,q[u].state,sizeof(goal))==0 && q[rear].room==q[u].room)	
			return 0;
		u	= next[u];
	}
	next[rear]	= head[h];
	head[h]		= rear;
	return 1;
}
int solve(int n)//n房间号
{
	int front=1,rear=2,i,j;
	q[front].parent	= -1;q[front].room	= 1;q[front].state[1] = 1;
	try_insert(1);
	while(front<rear)
	{
		Node&	cur	= q[front];
		if(memcmp(cur.state,goal,sizeof(goal))==0 && cur.room==r)	
			return front;
		//是否有可行通路
		for(i=1; i<=r; i++)
		{
			if(G[cur.room][i] && cur.state[i])
			{
				memcpy(&q[rear], &cur, sizeof(Node));
				q[rear].dist += 1;
				q[rear].oper  = MOV;
				q[rear].parent= front;
				q[rear].room  = i;
				q[rear].to	  = i;
				if(try_insert(rear))	
					rear++;
			}
		}
		//是否有开关灯操作
		for(i=1; i<=r; i++)
		{
			if(control[cur.room][i] && (cur.room!=i) )
			{
				memcpy(&q[rear], &cur, sizeof(Node));
				if(cur.state[i])
					q[rear].oper	= OFF;
				else
					q[rear].oper	= ON;
				q[rear].dist	+= 1;
				q[rear].parent	 = front;
				q[rear].state[i] = !q[rear].state[i];
				q[rear].to		 = i;
				if(try_insert(rear))	
					rear++;
			}
		}
		front++;
	}
	return 0;
}

void output(int cur)
{
	int i;
	if(cur==-1)	
		return;
	output(q[cur].parent);
	switch(q[cur].oper)
	{
		case MOV:
			printf("- Move to room %d.\n",q[cur].to);
			break;
		case ON:
			printf("- Switch on light in room %d.\n",q[cur].to);
			break;		
		case OFF:
			printf("- Switch off light in room %d.\n",q[cur].to);
			break;
	}
}
int main() 
{
	int res=-1,cs=0;
	while(scanf("%d %d %d",&r,&d,&s)==3)
	{
		if(r==0)	break;
		if(res==0)	printf("\n\n");
		input();
		res = solve(1);
		printf("Villa #%d\n",++cs);
		if(res==0)	printf("The problem cannot be solved.");
		else
		{
			printf("The problem can be solved in %d steps:\n",q[res].dist);
			output(res);printf("\n");
		}
	}
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值