HDOJ2828-DLX, 重複覆蓋小變形

代碼是昨天寫的,今天又試着做重複覆蓋的DLX,發現根本寫不下,出現了重重錯誤,我還以爲我昨天誤打誤撞的代碼很優咧,太自以爲是了!這道HDOJ2828也是好題,它比我今天試寫的HDOJ3957簡單得多,最大的不同不是一個只是求一個YES/NO,另一個求的是最小dfs深度,而是3957的鏈表數據中的關係比2828複雜,所以dance實現部分的思想都是不一樣的~

**尚未成功,菜鳥仍需努力~不想說revolution那個凝重的詞。

// 第二個Dancing links,1Y,0ms,暫時排名第五,挺興奮的!
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;

const int NN=505;
const int MM=51000;

int n,m,cnt,R[MM],L[MM],U[MM],D[MM],C[MM],H[MM],flag[MM];
int S[NN],O[NN],V[NN];

void init()//這裏的十字鏈表以燈爲列,開關爲行
{
    cnt=n;
    for (int i=0; i<=n; i++)
    {
        D[i]=U[i]=i;
        R[i]=i+1;
        L[i+1]=i;
        S[i]=0;
    }
    L[0]=n,R[n]=0;
    for (int i=1; i<=m; i++) V[i]=0;
}

void add_link(int i,int j,int t)
{
    C[++cnt]=i;
    H[cnt]=j;
    S[i]++;
    flag[cnt]=t;  //開關狀態

    D[cnt]=i;
    U[cnt]=U[i];
    if (V[j]) R[cnt]=V[j],L[cnt]=L[V[j]];
    else      R[cnt]=L[cnt]=cnt;
    V[j]=cnt;

    U[D[cnt]]=cnt;
    D[U[cnt]]=cnt;
    R[L[cnt]]=cnt;
    L[R[cnt]]=cnt;
}

void remove(int c)//題意不同,這裏remove有變,指的是刪除c列
{
    L[R[c]]=L[c];
    R[L[c]]=R[c];
    for (int i=D[c]; i!=c; i=D[i])
    {
        L[R[i]]=L[i];
        R[L[i]]=R[i];
        S[C[i]]--;
    }
}

void resume(int c)
{
    for (int i=U[c]; i!=c; i=U[i])
    {
        R[L[i]]=i;
        L[R[i]]=i;
        S[C[i]]++;
    }
    R[L[c]]=L[R[c]]=c;
}

bool dance()
{
    if (!R[0])
    {
        for (int i=1; i<m; i++) printf(O[i]==1?"ON ":"OFF ");
        puts(O[m]==1?"ON":"OFF");
        return 1;
    }
    int c,s=MM,i,j;
    for (i=R[0]; i; i=R[i]) if (S[i]<s) s=S[c=i];
    if (s==0) return 0; //s==0說明沒有開關能使燈c處於ON的狀態了
    
    R[L[c]]=R[c]; L[R[c]]=L[c]; //這裏只需刪去列指針c即可
    for (i=D[c]; i!=c; i=D[i])
    {
        O[H[i]]=flag[i];//記錄答案
        for (int j=R[i]; j!=i; j=R[j])
        {
            if (flag[j]==flag[i]) remove(C[j]);
            else D[U[j]]=D[j],U[D[j]]=U[j],S[C[j]]++;//這裏沒寫S[C[j]]--時也過了,想想確實不影響正確性
        }
        if (dance()) return 1;
        for (int j=L[i]; j!=i; j=L[j])
        {
            if (flag[j]==flag[i]) resume(C[j]);
            else U[D[j]]=j,D[U[j]]=j,S[C[j]]--;
        }
    }
    R[L[c]]=c; L[R[c]]=c;//恢復列指針c
    return 0;
}

int main()
{
    int k,x;
    char str[5];
    while (~scanf("%d%d",&n,&m))
    {
        init();
        for (int i=1; i<=n; i++)
        {
            scanf("%d",&k);
            while (k--)
            {
                scanf("%d%s",&x,&str);
                if (str[1]=='N') add_link(i,x,1);
                else             add_link(i,x,0);
            }
        }
        if (!dance()) puts("-1");
    }
    return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章