HDOJ 2828 Lamp DLX重复覆盖

DLX重复覆盖模版题:

每个开关两个状态,但只能选一个,建2m×n的矩阵跑DLX模版。。。。

Lamp

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)

Total Submission(s): 855    Accepted Submission(s): 265

Special Judge

Problem Description

There are several switches and lamps in the room, however, the connections between them are very complicated. One lamp may be controlled by several switches, and one switch may controls at most two lamps. And what’s more, some connections are reversed by mistake,
so it’s possible that some lamp is lighted when its corresponding switch is “OFF”!

To make things easier, we number all the lamps from 1 to N, and all the switches 1 to M. For each lamps, we give a list of switches controlling it. For example, for Lamp 1, the list is “1 ON 3 OFF 9 ON”, that means Lamp 1 will be lighted if the Switch 1 is
at the “ON” state OR the Switch 3 is “OFF” OR the Switch 9 is “ON”.

Now you are requested to turn on or off the switches to make all the lamps lighted.

Input

There are several test cases in the input. The first line of each test case contains N and M (1 <= N,M <= 500), then N lines follow, each indicating one lamp. Each line begins with a number K, indicating the number of switches controlling this lamp, then K
pairs of “x ON” or “x OFF” follow.

Output

Output one line for each test case, each contains M strings “ON” or “OFF”, indicating the corresponding state of the switches. For the solution may be not unique, any correct answer will be OK. If there are no solutions, output “-1” instead.

Sample Input

2 2
2 1 ON 2 ON
1 1 OFF
2 1
1 1 ON
1 1 OFF

Sample Output

OFF ON
-1

Source

2009 Multi-University Training Contest 2 - Host
by TJU

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>

using namespace std;

const int maxn=1010,maxm=510;
const int maxnode=maxn*maxm;
const int INF=0x3f3f3f3f;

int n,m;
bool flag;

struct DLX
{
    int n,m,size;
    int U[maxnode],D[maxnode],R[maxnode],L[maxnode],Row[maxnode],Col[maxnode];
    int H[maxn],S[maxm];
    int ansd,ans[maxn];
    int LAMP[maxn];
    bool vis[maxn];
    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-1; R[i]=i+1;
        }
        R[m]=0; L[0]=m;
        size=m;
        for(int i=1;i<=n;i++)
        {
            vis[i]=false;
            LAMP[i]=0;
            H[i]=-1;
        }
        flag=false;
    }
    void Link(int r,int c)
    {
        ++S[Col[++size]=c];
        Row[size]=r;
        D[size]=D[c];
        U[D[c]]=size;
        U[size]=c;
        D[c]=size;
        if(H[r]<0) H[r]=L[size]=R[size]=size;
        else
        {
            R[size]=R[H[r]];
            L[R[H[r]]]=size;
            L[size]=H[r];
            R[H[r]]=size;
        }
    }
    void remove(int c)
    {
        for(int i=D[c];i!=c;i=D[i])
            L[R[i]]=L[i],R[L[i]]=R[i];
    }
    void resume(int c)
    {
        for(int i=U[c];i!=c;i=U[i])
            L[R[i]]=R[L[i]]=i;
    }
    void Dance(int d)
    {
        if(flag) return ;
        if(R[0]==0)
        {
            ///find ans
            for(int i=0;i<d;i++)
            {
               int lamp=(ans[i]+1)/2;
               if(ans[i]%2) LAMP[lamp]=1;
            }
            for(int i=1;i<=n/2;i++)
            {
                if(LAMP[i]==1) printf("ON");
                else printf("OFF");
                if(i!=n/2) putchar(32); else putchar(10);
            }
            flag=true;
            return ;
        }
        int c=R[0];
        for(int i=R[0];i!=0;i=R[i])
        {
            if(S[i]<S[c]) c=i;
        }
        for(int i=D[c];i!=c;i=D[i])
        {
            if(vis[Row[i]]) continue;
            int r1=Row[i],r2=Row[i];
            if(r1%2==0) r2--;else r2++;
            vis[r1]=true; vis[r2]=true;
            remove(i);
            for(int j=R[i];j!=i;j=R[j]) remove(j);
            ans[d]=Row[i];
            Dance(d+1);
            for(int j=L[i];j!=i;j=L[j]) resume(j);
            resume(i);
            vis[r1]=false; vis[r2]=false;
        }
    }
};

DLX dlx;

int main()
{
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        dlx.init(2*m,n);
        for(int i=1;i<=n;i++)
        {
            int k;
            scanf("%d",&k);
            for(int j=0;j<k;j++)
            {
                int p; char sw[20];
                scanf("%d%s",&p,sw);
                if(sw[1]=='N') dlx.Link(2*p-1,i);
                else if(sw[1]=='F') dlx.Link(2*p,i);
            }
        }
        dlx.Dance(0);
        if(flag==false) puts("-1");
    }
    return 0;
}
时间: 2024-10-10 11:54:44

HDOJ 2828 Lamp DLX重复覆盖的相关文章

[DLX重复覆盖] hdu 2828 Lamp

题意: 有N个灯M个开关 每个灯的ON和OFF状态都能控制一个灯是否亮 给出N行,代表对于每个灯 哪些开关的哪个状态可以使得第i个灯亮 思路: 这里需要注意一个问题 如果开关1的ON 状态和开关2的ON状态能使得1号灯亮 那么开关1.2同时处于ON的时候 1号灯也是亮的.意思就是只要有一个开关使得灯亮,灯就亮了. 简单的DLX 重复覆盖 行为每个开关的两个状态2*m行,列为n个灯 在搜索的同时标记一下哪个开关被用过了 那么另一个状态也不能用了 代码: #include"stdio.h"

FZU 1686 神龙的难题(DLX重复覆盖)

FZU 1686 神龙的难题 题目链接 题意:中文题 思路:每一个1看成列,每个位置作为左上角的矩阵看成行,dlx重复覆盖即可 代码: #include <cstdio> #include <cstring> using namespace std; const int MAXNODE = 66666; const int INF = 0x3f3f3f3f; const int MAXM = 230; const int MAXN = 230; int K; struct DLX

HDU 5046 Airport(DLX重复覆盖)

HDU 5046 Airport 题目链接 题意:给定一些机场,要求选出K个机场,使得其他机场到其他机场的最大值最小 思路:二分+DLX重复覆盖去判断即可 代码: #include <cstdio> #include <cstring> using namespace std; const int MAXNODE = 4005; const int MAXM = 65; const int MAXN = 65; const int INF = 0x3f3f3f3f; int K;

[ACM] HDU 2295 Radar (二分+DLX 重复覆盖)

Radar Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2593    Accepted Submission(s): 1012 Problem Description N cities of the Java Kingdom need to be covered by radars for being in a state of

FZU 1686 神龙的难题 DLX重复覆盖

DLX重复覆盖: 需要一个A*函数剪支 Problem 1686 神龙的难题 Accept: 462    Submit: 1401 Time Limit: 1000 mSec    Memory Limit : 32768 KB  Problem Description 这是个剑与魔法的世界.英雄和魔物同在,动荡和安定并存.但总的来说,库尔特王国是个安宁的国家,人民安居乐业,魔物也比较少.但是.总有一些魔物不时会进入城市附近,干扰人民的生活.就要有一些人出来守护居民们不被魔物侵害.魔法使艾米莉

[DLX重复覆盖] fzu 1686 神龙的难题

题意: 中文题 思路: 想到是一个重复覆盖的问题,然后就是最少放多少个能覆盖满. 建图的话就是先标记一下哪些点有怪物,最多就是n*m个怪物. 然后就是行. 行的话就看输入的x和y能框住多少的范围了. 然后四重循环遍历一遍建边就ok了. 代码: #include"stdio.h" #include"algorithm" #include"string.h" #include"iostream" #include"cma

hdu 2295 dlx重复覆盖+二分答案

题目大意: 有一堆雷达工作站,安放至多k个人在这些工作站中,找到一个最小的雷达监控半径可以使k个工作人所在的雷达工作站覆盖所有城市 二分半径的答案,每次利用dlx的重复覆盖来判断这个答案是否正确 1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 #include <algorithm> 5 #include <queue> 6 #include <climits

HDU 2295.Radar (DLX重复覆盖)

2分答案+DLX判断可行 不使用的估计函数的可重复覆盖的搜索树将十分庞大 #include <iostream> #include <cstring> #include <cstdio> #include <cmath> #include <vector> using namespace std; #define FOR(i,A,s) for(int i = A[s]; i != s; i = A[i]) #define exp 1e-8 con

[DLX重复覆盖] hdu 3498 whosyourdaddy

题意: 给N个怪,M个关系. 每个关系代表a和b是邻居. 然后问每次攻击你可以攻击一个怪以及它的全部邻居 问最少需要几次攻击能把怪全部杀死. 思路: 怪为行和列,然后对面每个怪的邻居都是这个怪的列建图. 也是比较裸的重复覆盖. 代码: #include"cstdlib" #include"cstdio" #include"cstring" #include"cmath" #include"queue" #i