题意:给你n个房间,有许多灯的控制开关,i房间灯的开关在j房间,未开灯的房间不能进,i房间和j房间之间如果没有门,也不能从i进入到j,开始房间是1,并且灯是开着的,问你是否能够走到最后一个房间n,并且此时其他房间的灯都是关着的.如果存在多个解,输出操作步数最小的操作序列.
范围:n<=10,
解题思路:设状态为,当前的房间编号+当前其他房间灯的状态.所以总的状态为N*2^N,最大值10*1024,裸枚举.
注意,这道题目每次枚举都必须从房间编码1-N,要不然会wa,而且,PE也wa.使用了位标志房间灯的状态.
#include <iostream> #include<map> #include<memory.h> #include<stdio.h> #include<string> #include<queue> #include<vector> using namespace std; const int MAXN = 11; class Node { public: vector<string>step; int cur; int curStepNum; int lights; Node() { //step.reserve(65535); } bool operator <(const Node& node) const { return curStepNum > node.curStepNum; }; }; int conn[MAXN][MAXN]; int contro[MAXN][MAXN]; int r, d, s; int states[10][1025]; priority_queue<Node>q; int perLights[10] = { 1 << 0,1 << 1,1 << 2 ,1 << 3 ,1 << 4 ,1 << 5 , 1 << 6,1 << 7,1 << 8 ,1 << 9 }; void read() { int ss, ee; for (int i = 0;i < d;i++) { cin >> ss >> ee; //start with 0 conn[ss - 1][ee - 1] = 1; conn[ee - 1][ss - 1] = 1; } for (int i = 0;i < s;i++) { cin >> ss >> ee; contro[ss - 1][ee - 1] = 1; } } Node bfs() { Node node; node.cur = 0; node.curStepNum = 0; node.lights = 1; q.push(node); //init node 只有0房间是亮的 states[0][1] = 1; while (q.empty() == false) { node = q.top(); q.pop(); int curIndex = node.cur; //cur lights state int curLights = node.lights; int curStepNum = node.curStepNum; //判断是不是终点 if ((curIndex == r - 1) && curLights == perLights[r - 1]) { return node; } //枚举灯的状态 for (int i = 0;i < 10; i++) { if (contro[curIndex][i] == 0) continue; if (i == curIndex) continue; //控制的灯 int nextControLightIndex = i; string desc = ""; int nextLight = 0; if ((curLights & perLights[nextControLightIndex]) == perLights[nextControLightIndex]) { //关闭next房间的灯 nextLight = (curLights ^ perLights[nextControLightIndex]); if (states[curIndex][nextLight] == 1) //repeat continue; desc = "- Switch off light in room " + std::to_string(nextControLightIndex + 1); desc += "."; } else { //打开next房间的灯 nextLight = curLights | perLights[nextControLightIndex]; if (states[curIndex][nextLight] == 1) //repeat continue; desc = "- Switch on light in room " + std::to_string(nextControLightIndex + 1); desc += "."; } Node newNode; newNode.curStepNum = curStepNum + 1; newNode.cur = curIndex; newNode.lights = nextLight; newNode.step = node.step; newNode.step.push_back(desc); //push to queue q.push(newNode); states[curIndex][nextLight] = 1; } //end curIndex enum lights state //start door for (int i = 0;i < 10;i++) { if (curIndex == i) continue; if (conn[curIndex][i] == 0) continue; int nextDoor = i; if ((perLights[nextDoor] & curLights) == 0) //灯是灭的,不能进 continue; if (states[nextDoor][curLights] == 1) //已经看到过,不能进 continue; //灯是开着的,能进 Node newNode; newNode.cur = nextDoor; newNode.curStepNum = curStepNum + 1; newNode.lights = curLights; newNode.step = node.step; string desc = "- Move to room " + std::to_string(nextDoor + 1); desc += "."; newNode.step.push_back(desc); states[nextDoor][curLights] = 1; q.push(newNode); } } node.cur = -1; return node; } int main() { int t = 0; while (cin >> r >> d >> s) { if (r == d && d == s && r == 0) break; memset(conn, 0, sizeof(conn)); memset(contro, 0, sizeof(conn)); memset(states, 0, sizeof(states)); while (q.empty() == false) q.pop(); read(); cout << "Villa #"; cout << t + 1 << endl; if (r == 1) { cout << "The problem can be solved in " << 0 << " steps:" << endl; } else { Node node = bfs(); //cout << "test" << endl; if (node.cur == -1) { cout << "The problem cannot be solved." << endl; } else { cout << "The problem can be solved in " << node.curStepNum << " steps:" << endl; vector<string> b = node.step; for (int i = 0;i <= b.size() - 1;i++) cout << b[i] << endl;; } } t++; cout << endl; } }