poj 3740 DLX(精确覆盖)

来源:互联网 发布:监控网络硬盘服务器 编辑:程序博客网 时间:2024/04/27 15:40

题意:经典的精确覆盖问题。

思路:精确覆盖问题是NPC的,用DLX能够比较有效的搜索。写完两个数独再写这个就不难了(实际上这个是原始问题,数独只是DLX的应用)。

#include <cstdio>#include <cstring>#define N 16#define M 300struct node{    int l,r,u,d,x,y;}p[N*M+M+5];int s[N+5][M+5];int n,m,top,cnt[M];void init(){    int i;    memset(cnt, 0, sizeof(cnt));    for(i = 0;i<=m;i++){        p[i].l = i-1;        p[i].r = i+1;        p[i].u = p[i].d = i;    }    p[0].l = m;    p[m].r = 0;    top = m;}void add(int l,int i,int j){    p[++top].x = i;    p[top].y = j;    p[top].l = l;    p[p[top].l].r = top;    p[top].u = p[j].u;    p[p[top].u].d = top;    p[j].u = top;    p[top].d = j;    cnt[j]++;}void del(int c){    int i,j;    p[p[c].l].r = p[c].r;    p[p[c].r].l = p[c].l;    for(i = p[c].d;i!=c;i=p[i].d){        for(j = p[i].r;j!=i;j=p[j].r){            p[p[j].u].d = p[j].d;            p[p[j].d].u = p[j].u;            cnt[p[j].y]--;        }    }}void re(int c){    int i,j;    p[p[c].l].r = c;    p[p[c].r].l = c;    for(i = p[c].d;i!=c;i=p[i].d)        for(j = p[i].r;j!=i;j=p[j].r){            p[p[j].u].d = j;            p[p[j].d].u = j;            cnt[p[j].y]++;        }}int dfs(){    int min=0x3fffffff,c=0,i,j;    if(!p[0].r)        return 1;    for(i = p[0].r;i;i=p[i].r)        if(cnt[i] < min){            c = i;            min = cnt[i];        }    del(c);    for(i = p[c].d;i!=c;i=p[i].d){        for(j = p[i].r;j!=i;j=p[j].r)            del(p[j].y);        if(dfs())            return 1;        for(j = p[i].l;j!=i;j=p[j].l)            re(p[j].y);    }    re(c);    return 0;}int main(){    while(scanf("%d %d",&n,&m)!=EOF){        int i,j,first;        init();        for(i = 1;i<=n;i++){            s[i][0] = 0;//保存一行中1的个数            for(j = 1;j<=m;j++){                scanf("%d",&s[i][j]);                if(s[i][j])                    s[i][0]++;            }        }        for(i = 1;i<=n;i++)            for(j = first = 1;j<=m;j++)                if(s[i][j]){                    if(first){                        first = 0;                        add(top+s[i][0], i, j);                    }else                        add(top, i, j);                }        if(dfs())            printf("Yes, I found it\n");        else            printf("It is impossible\n");    }    return 0;}


0 0