UVA321

首先输入三个数字 r ,d ,s     r代表房间的数量,d代表门的数量,也就是房间连通的数量,s代表开关的数量。然后接下去 d + s 行是门和开关的描述。


题目的意思是这样的,有r个房间,每个房间的开关可以控制其它房间的灯,你只能走灯亮的房间,然后要走到第r个房间,并且其它房间灯都暗的。你现在在房间1 并且房间1灯是亮的,要求几个步骤可以到达这种状态,状态改变可以是 开灯,关灯,走到其它房间。

首先我们一个数组保存状态,数组第一个位置代表现在所处的房间,接下去用‘0’ ‘1’ 表示每个房间的灯是开还是关,用map <string ,int>判重。

然后就是bfs()把每一种状态入队列;

有一点要注意,就是这题最后要把所有步骤输出,所以我把记录步骤分成两部分,第一部分开灯关灯还是移动,分别用1,2,3,


AC代码:


#include <stdio.h>
#include <string.h>
#include <string>
#include <queue>
#include <map>
using namespace std;

const int N = 15 + 5;
int r, d, s;
bool ok;
char tar[N];
int link[N][N], swlink[N][N];
struct state {
    char s[N];
    int step[10005];
    int stepnum;
    int room;
} st,st1;
map<string, int> vis;
queue<state> q;
void bfs() {
	ok = false;
	vis.clear();
	while (!q.empty()) {
		q.pop();
	}
	st.room = 1;
	st.s[0] = '1';
   	st.s[1] = '1';
	for (int i = 2; i <= r; i ++) {
		st.s[i] = '0';
	}
	st.s[r + 1] = '\0';
	st.stepnum = 0;
	vis[st.s] = 1;
	q.push(st);
	while (!q.empty()) {
		st = q.front();
		if (strcmp(st.s,tar) == 0) {
			ok = true;
			return;
		}
		q.pop();
		for (int i = 1; i <= r; i++) {
			st1 = st;
			if (link[st1.room][i] && st1.s[i] == '1') {
				st1.s[0] = i + '0';   
				if (!vis[st1.s]) {
					vis[st1.s] = 1;
					st1.room = i;
					st1.step[st1.stepnum ++] = 3;
					st1.step[st1.stepnum ++] = i;
					q.push(st1);
				}
			}
			st1 = st;
			if (swlink[st1.room][i] && i != st1.room) {
				if (st1.s[i] == '1') {
					st1.s[i] = '0';
					st1.step[st1.stepnum ++] = 2;
					st1.step[st1.stepnum ++] = i;
				}
				else {
					st1.s[i] = '1';
					st1.step[st1.stepnum ++] = 1;
					st1.step[st1.stepnum ++] = i;
				}
				if (!vis[st1.s]) {
					vis[st1.s] = 1;
					q.push(st1);
				}
			}
		}
	}
}
int main() {
	int t = 1;
	while (scanf("%d%d%d", &r, &d, &s) != EOF && (r + d + s)) {
		int temp, temp2;
		memset(link, 0, sizeof(link));
		memset(swlink, 0, sizeof(swlink));
		tar[0] = r + '0';
	   	tar[r] = '1';
	   	tar[r + 1] = '\0';
		for (int i = 1; i < r; i ++)
			tar[i] = '0';
		for (int i = 0; i < d; i ++) {
			scanf("%d%d", &temp, &temp2);
			link[temp][temp2] = link[temp2][temp] = 1;
		}
		for (int i = 0; i < s; i ++) {
			scanf("%d%d", &temp, &temp2);
			swlink[temp][temp2] = 1;
		}
		bfs();
		printf("Villa #%d\n", t ++);
		if (ok) {
			printf("The problem can be solved in %d steps:\n", (st.stepnum + 1) / 2);
			for (int i = 0; i < st.stepnum; i ++) {
				if (i % 2 == 0) {
					if (st.step[i] == 1)
						printf("- Switch on light in room ");
					if (st.step[i] == 2)
						printf("- Switch off light in room ");
					if (st.step[i] == 3)
						printf("- Move to room ");
				}
				if (i % 2) {
					printf("%d.\n", st.step[i]);
				}
			}
		}
		else
			printf("The problem cannot be solved.\n");
		printf("\n");
	}
	return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值