• 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;
        }
    
    
    }
  • 相关阅读:
    多表联查统计数字
    在null情况下判断
    一个搜索框实现同一表内多个属性的搜索
    分页固定显示信息数
    git常用命令
    java 常用知识点
    Win10 系统直接在目录下打开cmd
    Linux环境 通过sftp启动jar包
    使用Navicat导出可执行脚本 SqlServer数据库某表的部分数据
    C#常用快捷键
  • 原文地址:https://www.cnblogs.com/shuiyonglewodezzzzz/p/9827556.html
Copyright © 2020-2023  润新知