P2622 关灯问题II (状态压缩入门)

题目链接: https://www.luogu.org/problemnew/show/P2622

具体思路:暴力,尝试每个开关,然后看所有的情况中存不存在灯全部关闭的情况,在储存所有灯的情况的时候,观察到n的值不大,所以可以考虑用二进制进行存储,如果说这个数用二进制表示的时候,如果第i位是1,代表第(i+1)个灯当前的状态是开着的,否则就是关闭的.

AC代码:

#include<iostream>
#include<cstring>
#include<iomanip>
#include<algorithm>
#include<queue>
#include<stdio.h>
#include<cmath>
using namespace std;
# define inf 0x3f3f3f3f
# define ll long long
# define pi acos(-1.0)
const int mod = 1e9 ;
const int maxn = 200+100;
struct node
{
    int num;
    int step;
    node() {}
    node(int xx,int yy)
    {
        num=xx;
        step=yy;
    }
};
int a[maxn][maxn];
int vis[6000],n,m;
int bfs(int tot)
{
    queue<node>q;
    vis[tot]=1;
    q.push(node(tot,0));
    while(!q.empty())
    {
        node top=q.front();
        q.pop();
        int t=top.num;
        for(int i=1; i<=n; i++)
        {
            int tmp=t;
            for(int j=1; j<=m; j++)
            {
                if(a[i][j]==1)
                {
                    if(tmp&(1<<(j-1)))//如果说当前的灯是开着的,就改成关闭
                        tmp=tmp^(1<<(j-1));
                }
                if(a[i][j]==-1)
                {
                    tmp=tmp|(1<<(j-1));//改成开启的状态
                }
            }
            if(vis[tmp])continue;
            vis[tmp]=1;
            q.push(node(tmp,top.step+1));
            if(tmp==0)
            {
                return top.step+1;
            }
        }
    }
    return -1;
}
int main()
{
    scanf("%d%d",&m,&n);
    for(int i=1; i<=n; i++)
    {
        for(int j=1; j<=m; j++)
        {
            scanf("%d",&a[i][j]);
        }
    }
    int tmp=(1<<m)-1;//初始状态,每一位上都是1
    int ans=bfs(tmp);
    printf("%d\n",ans);
    return 0;
}

 

posted @ 2018-12-13 16:38  Let_Life_Stop  阅读(149)  评论(0编辑  收藏  举报