1. 程式人生 > >uva-321-暴力列舉-隱式圖搜尋

uva-321-暴力列舉-隱式圖搜尋

題意:給你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; } }