[DLX重复覆盖] hdu 2828 Lamp

来源:互联网 发布:java验证码代码怎么写 编辑:程序博客网 时间:2024/06/05 05:37

题意:

有N个灯M个开关

每个灯的ON和OFF状态都能控制一个灯是否亮

给出N行,代表对于每个灯

哪些开关的哪个状态可以使得第i个灯亮

思路:

这里需要注意一个问题 

如果开关1的ON 状态和开关2的ON状态能使得1号灯亮

那么开关1、2同时处于ON的时候 1号灯也是亮的。意思就是只要有一个开关使得灯亮,灯就亮了。

简单的DLX 重复覆盖

行为每个开关的两个状态2*m行,列为n个灯

在搜索的同时标记一下哪个开关被用过了

那么另一个状态也不能用了

代码:

#include"stdio.h"#include"algorithm"#include"string.h"#include"iostream"#include"queue"#include"map"#include"vector"#include"string"using namespace std;#define N 1005*1005#define RN 1005#define CN 1005int us[RN];struct DLX{    int n,m,C;    int U[N],D[N],L[N],R[N],Row[N],Col[N];    int H[RN],S[CN],cnt,ans[RN];    void init(int _n,int _m)    {        n=_n;        m=_m;        for(int i=0; i<=m; i++)        {            S[i]=0;            U[i]=D[i]=i;            L[i]=(i==0?m:i-1);            R[i]=(i==m?0:i+1);        }        C=m;        for(int i=1; i<=n; i++) H[i]=-1;    }    void link(int x,int y)    {        C++;        Row[C]=x;        Col[C]=y;        S[y]++;        U[C]=U[y];        D[C]=y;        D[U[y]]=C;        U[y]=C;        if(H[x]==-1) H[x]=L[C]=R[C]=C;        else        {            L[C]=L[H[x]];            R[C]=H[x];            R[L[H[x]]]=C;            L[H[x]]=C;        }    }    void del(int x)    {        for(int i=D[x]; i!=x; i=D[i])        {            R[L[i]]=R[i];            L[R[i]]=L[i];        }    }    void rec(int x)    {        for(int i=U[x]; i!=x; i=U[i])        {            R[L[i]]=i;            L[R[i]]=i;        }    }    int used[CN];    int h()    {        int sum=0;        for(int i=R[0]; i!=0; i=R[i]) used[i]=0;        for(int i=R[0]; i!=0; i=R[i])        {            if(used[i]==0)            {                sum++;                used[i]=1;                for(int j=D[i]; j!=i; j=D[j]) for(int k=R[j]; k!=j; k=R[k]) used[Col[k]]=1;            }        }        return sum;    }    int dance(int x)    {        //if(x+h()>=cnt) return 0;        if(R[0]==0)        {            cnt=x;            // cnt=min(cnt,x);            return 1;        }        int now=R[0];        for(int i=R[0]; i!=0; i=R[i])        {            if(S[i]<S[now])                now=i;        }        for(int i=D[now]; i!=now; i=D[i])        {            if(us[(Row[i]-1)/2+1]==0)            {                us[(Row[i]-1)/2+1]=1;                del(i);                ans[x]=Row[i];                for(int j=R[i]; j!=i; j=R[j]) del(j);                if(dance(x+1)) return 1;                for(int j=L[i]; j!=i; j=L[j]) rec(j);                rec(i);                us[(Row[i]-1)/2+1]=0;            }        }        return 0;    }} dlx;int main(){    int n,m;    while(scanf("%d%d",&n,&m)!=-1)    {        dlx.init(2*m,n);        for(int i=1; i<=n; i++)        {            int k;            scanf("%d",&k);            while(k--)            {                int x;                char y[21];                scanf("%d%s",&x,y);                int tep=x*2-1;                if(strcmp(y,"OFF")==0) tep++;                dlx.link(tep,i);            }        }        memset(us,0,sizeof(us));        int f=dlx.dance(0);        if(f==0) puts("-1");        else        {            memset(us,0,sizeof(us));            for(int i=0;i<dlx.cnt;i++)            {                us[(dlx.ans[i]-1)/2+1]=dlx.ans[i]%2;            }            for(int i=1;i<=m;i++) printf(i==m?"%s\n":"%s ",us[i]==0?"OFF":"ON");        }    }    return 0;}


0 0