• 洛谷 P2622 关灯问题II (状态压缩+BFS)


    题目描述
    现有n盏灯,以及m个按钮。每个按钮可以同时控制这n盏灯——按下了第i个按钮,对于所有的灯都有一个效果。按下i按钮对于第j盏灯,是下面3中效果之一:如果a[i][j]为1,那么当这盏灯开了的时候,把它关上,否则不管;如果为-1的话,如果这盏灯是关的,那么把它打开,否则也不管;如果是0,无论这灯是否开,都不管。

    现在这些灯都是开的,给出所有开关对所有灯的控制效果,求问最少要按几下按钮才能全部关掉。

    输入输出格式
    输入格式:
    前两行两个数,n m

    接下来m行,每行n个数,a[i][j]表示第i个开关对第j个灯的效果。

    输出格式:
    一个整数,表示最少按按钮次数。如果没有任何办法使其全部关闭,输出-1

    输入输出样例
    输入样例#1:
    3
    2
    1 0 1
    -1 1 0
    输出样例#1:
    2
    说明
    对于20%数据,输出无解可以得分。

    对于20%数据,n<=5

    对于20%数据,m<=20

    上面的数据点可能会重叠。

    对于100%数据 n<=10,m<=100

    题意:

    思路:

    用一个int类型的整数state 来记录当前灯泡的状态, 二进制来描述信息
    state 的第i位为1,表示第i个灯泡现在是亮的,否则是灭掉的。
    然后暴力去跑BFS, 同时用一个数组VIS标记哪些状态被访问了,而利用bfs的性质,后面一个状态state,如果 vis[state] =1 表明在前面被访问过了,那么这一个就可以忽略了,因为前面的步数step一定小于等于当前的step.

    细节见代码:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    #include <queue>
    #include <stack>
    #include <map>
    #include <set>
    #include <vector>
    #include <iomanip>
    #define ALL(x) (x).begin(), (x).end()
    #define rt return
    #define dll(x) scanf("%I64d",&x)
    #define xll(x) printf("%I64d
    ",x)
    #define sz(a) int(a.size())
    #define all(a) a.begin(), a.end()
    #define rep(i,x,n) for(int i=x;i<n;i++)
    #define repd(i,x,n) for(int i=x;i<=n;i++)
    #define pii pair<int,int>
    #define pll pair<long long ,long long>
    #define gbtb ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
    #define MS0(X) memset((X), 0, sizeof((X)))
    #define MSC0(X) memset((X), '', sizeof((X)))
    #define pb push_back
    #define mp make_pair
    #define fi first
    #define se second
    #define eps 1e-6
    #define gg(x) getInt(&x)
    #define chu(x) cout<<"["<<#x<<" "<<(x)<<"]"<<endl
    using namespace std;
    typedef long long ll;
    ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
    ll lcm(ll a,ll b){return a/gcd(a,b)*b;}
    ll powmod(ll a,ll b,ll MOD){ll ans=1;while(b){if(b%2)ans=ans*a%MOD;a=a*a%MOD;b/=2;}return ans;}
    inline void getInt(int* p);
    const int maxn=1000010;
    const int inf=0x3f3f3f3f;
    /*** TEMPLATE CODE * * STARTS HERE ***/
    int n,m;
    bool flag=1;
    int a[105][105];
    int ans=inf;
    struct node
    {
        int state;
        int step;
        node(){}
        node(int st,int sstep)
        {
            state=st;
            step=sstep;
        }
    };
    queue<node> q;
    int vis[2500];
    void bfs()
    {
        int num=0;
        for(int i=1;i<=n;i++)
        {
            num|=(1<<i);
        }
        q.push(node(num,0));
        node temp;
        int cnt=0;
        while(flag&&!q.empty())
        {
            temp=q.front();
            q.pop();
            cnt++;
            if(temp.state==0)
            {
                ans=min(ans,temp.step);
                flag=0;
                break;
            }
            for(int i=1;i<=m;i++)
            {
                num=temp.state;
                for(int j=1;j<=n;j++)
                {
                    if (a[i][j]==1)
                    {
                        if((num&(1<<j))>0)
                        {
                            num-=(1<<j);
                        }
                    }else if(a[i][j]==-1)
                    {
                        if((num&(1<<j))==0)
                        {
                            num+=(1<<j);
                        }
                    }
                }
                if(!vis[num])
                {
                    q.push(node(num,temp.step+1));
                    vis[num]=1;
                }
            }
        }
    
    }
    int main()
    {
        // freopen("D:\common_text\code_stream\in.txt","r",stdin);
        //freopen("D:common_textcode_streamout.txt","w",stdout);
        gbtb;
        // cout<<(1<<10)<<endl;
        cin>>n>>m;
        repd(i,1,m)
        {
            repd(j,1,n)
            {
                cin>>a[i][j];
            }
        }
        bfs();
        if(ans==inf)
        {
            ans=-1;
        }
        cout<<ans<<endl;
        
        
        return 0;
    }
    
    inline void getInt(int* p) {
        char ch;
        do {
            ch = getchar();
        } while (ch == ' ' || ch == '
    ');
        if (ch == '-') {
            *p = -(getchar() - '0');
            while ((ch = getchar()) >= '0' && ch <= '9') {
                *p = *p * 10 - ch + '0';
            }
        }
        else {
            *p = ch - '0';
            while ((ch = getchar()) >= '0' && ch <= '9') {
                *p = *p * 10 + ch - '0';
            }
        }
    }
    
    
    
    
    
    本博客为本人原创,如需转载,请必须声明博客的源地址。 本人博客地址为:www.cnblogs.com/qieqiemin/ 希望所写的文章对您有帮助。
  • 相关阅读:
    8.请描述基本数据类型和引用数据类型的区别?
    7.在第4题中Hello.class所在路径下, 输入命令:java Hello.class,会出现什么结果,为什么?
    6.如果第4题中在DOS命令下输入:java Hello 出现以下结果:Exception in thread “main” java.lang.NoClassDefFoundError: Hello
    5.如果第4题中在DOS命令下输入:java Hello 出现以下结果:Bad command or the file name 可能是什么原因?请说明理由。
    C# 反射技术应用
    C# 中的委托和事件
    类和结构的区别
    c#接口和抽象类的区别
    Repeater 控件使用总结
    SpringMvc+jquery easyui模块开发7步骤
  • 原文地址:https://www.cnblogs.com/qieqiemin/p/11146645.html
Copyright © 2020-2023  润新知