1. 程式人生 > >luogu p2622關燈問題II

luogu p2622關燈問題II

pac ont 之一 打開 con 表示 std -- ace

luogu p2622關燈問題II

題目描述

現有n盞燈,以及m個按鈕。每個按鈕可以同時控制這n盞燈——按下了第i個按鈕,對於所有的燈都有一個效果。按下i按鈕對於第j盞燈,是下面3中效果之一:如果a[i][j]為1,那麽當這盞燈開了的時候,把它關上,否則不管;如果為-1的話,如果這盞燈是關的,那麽把它打開,否則也不管;如果是0,無論這燈是否開,都不管。

現在這些燈都是開的,給出所有開關對所有燈的控制效果,求問最少要按幾下按鈕才能全部關掉。

輸入輸出格式

輸入格式:

前兩行兩個數,n m

接下來m行,每行n個數,a[i][j]表示第i個開關對第j個燈的效果。

輸出格式:

一個整數,表示最少按按鈕次數。如果沒有任何辦法使其全部關閉,輸出-1

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int n,m,a[110][11],f[1<<11],ans=0x3f3f3f3f;
int read()
{
    int n=0,f=1;char c=getchar();
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9'){n=n*10+c-'0';c=getchar();}
    return n*f;
}
int main()
{
    n=read(),m=read();
    for(int i=1;i<=m;++i)
        for(int j=1;j<=n;++j)
            a[i][j]=read();
    memset(f,0x3f,sizeof(f));
    f[(1<<n)-1]=0;
    for(int i=(1<<n)-1;i>0;--i)
    {
        for(int j=1;j<=m;++j)
        {
            int lpk=i;
            for(int k=1;k<=n;++k)
            {
                if(a[j][k]==0)continue;
                if(a[j][k]==1&&(i&(1<<(k-1))))lpk^=(1<<(k-1));
                if(a[j][k]==-1&&!(i&(1<<(k-1))))lpk^=(1<<(k-1));
            }
            f[lpk]=min(f[lpk],f[i]+1);
        }
    }
    if(f[0]>10000000)f[0]=-1;
    cout<<f[0];
    return 0;
}

luogu p2622關燈問題II