zoj 1301 The New Villa

很BT的搜索。。。

刚开始看题目的时候,也理解了题意,不过没想到要用什么算法。。

也有想到每一种状态都存起来,不过没想到该怎么样处理细节。。最后不得己在网上搜了下代码,。。

这题很BT的,,只是搜索就够麻烦了, 最后还要保存路径。。搞的头大。。

不过最后无论如何还是把它给A了。。。^_^ .

poj上的这道题目貌似不是special judje,,在poj上没能过去。。

题目大意:

黑先生新买了一栋别墅,可是里面的电灯线路的连接是很混乱的,有一天晚上他回家时发现所有的灯(除了他出发的房间)都是关闭的,而他想回卧室去休息。可是很不幸,他十分怕黑,因此他不会走入任何关着灯的房间,于是请你帮他找出一条路使他既能回到卧室又能关闭除卧室以外的所有灯。如果同时有好几条路线的话,请输出最短的路线。

中间有用到位运算,先给列出来。。

1<<n - 1 就是n位都是1
a & (1<<n) 获取 a 的 第 n - 1 位
a | (1<<n) 置a 的第 n 位为1
a ^ (1<<n) 置a 的第 n 位为原来的相反数

代码:

# include<stdio.h>
# include<string.h>
# include<stdlib.h>
# include<queue>
# define MAX 1100
using namespace std;
struct node{
	int room,state,step;
};
queue<node>q;
node cur,next,path[11][MAX];
int r,s,d,visit[12][MAX],adj[12][12],control[12][12],num[MAX],ch;
char ans[MAX][10];
int bfs()
{
	int i,temp;
	visit[1][1]=1;
	cur.room=1;
	cur.state=1;
	cur.step=0;
	while(!q.empty())
		q.pop();
	q.push(cur);
	while(!q.empty())
	{
		cur=q.front();
		q.pop();
		if(cur.room==r && cur.state==ch) return cur.step;
		for(i=1;i<=r;i++)/*先搞开关*/
		{
			if(cur.room==i || control[cur.room][i]==0) continue;
			next=cur;
			next.state=(next.state)^(1<<(i-1));/*转换第i个房间的状态*/
			if(visit[next.room][next.state]==0)
			{
				visit[next.room][next.state]=1;
				next.step=cur.step+1;
				q.push(next);
				path[next.room][next.state]=cur;
			}
		}
		/*进入相邻的房间*/
		for(i=1;i<=r;i++)
		{
			if(adj[cur.room][i]==0 || i==cur.room) continue;
			next=cur;
			next.room=i;
			temp=next.state&(1<<(i-1));/*判断第i个房间的灯光*/
			if(temp==0) continue;
			if(visit[next.room][next.state]==0)
			{
				visit[next.room][next.state]=1;
				next.step=cur.step+1;
				q.push(next);
				path[next.room][next.state]=cur;
			}
		}
	}
	return -1;
}
int main()
{
	int i,j,b,a,t=0,temp,top,x,y,k;
	while(scanf("%d%d%d",&r,&d,&s)!=EOF)
	{
		if(r==0 && s==0 && d==0) break;
		t++;
		printf("Villa #%d\n",t);
		memset(adj,0,sizeof(adj));
		memset(control,0,sizeof(control));
		memset(visit,0,sizeof(visit));
		for(i=0;i<=r;i++)
			for(j=0;j<=r;j++)
			{
				path[i][j].room=i;
				path[i][j].state=j;
			}
		for(i=1;i<=d;i++)
		{
			scanf("%d%d",&a,&b);
			adj[a][b]=1;
			adj[b][a]=1;
		}
		for(i=1;i<=s;i++)
		{
			scanf("%d%d",&a,&b);
			control[a][b]=1;
		}
		ch=1;
		for(i=1;i<r;i++)
			ch*=2;
		temp=bfs();
		if(temp==-1) 
		{
			printf("The problem cannot be solved.\n\n");
			continue;
		}
		printf("The problem can be solved in %d steps:\n",temp);
		i=r;
		j=ch;
		top=0;
		while(1)
		{
			if(path[i][j].room==i && path[i][j].state==j) break;
			if(path[i][j].room!=i)
			{
				strcpy(ans[top],"Move");
				num[top]=i;
				top++;
			}
			else
			{
				for(k=0;;k++)
				{
					x=j&(1<<k);
					y=path[i][j].state&(1<<k);
					if(x!=y) break;
				}
				if(x==0)
				{
					strcpy(ans[top],"off");
					num[top]=k+1;
					top++;
				}
				else 
				{
					strcpy(ans[top],"on");
					num[top]=k+1;
					top++;
				}
			}
			x=path[i][j].room;
			y=path[i][j].state;
			i=x;
			j=y;
		}
		for(i=top-1;i>=0;i--)
		{
			if(strcmp(ans[i],"Move")==0)
			{
				printf("- Move to room %d.\n",num[i]);
			}
			else if(strcmp(ans[i],"off")==0)
			{
				printf("- Switch off light in room %d.\n",num[i]);
			}
			else
			{
				printf("- Switch on light in room %d.\n",num[i]);
			}
		}
		printf("\n");
	}
	return 0;
}

转载于:https://www.cnblogs.com/183zyz/archive/2011/04/15/2017448.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值