DLX演算法合集 I

2021-06-28 18:53:12 字數 4528 閱讀 1092

dlx是一種相當神奇的資料結構,通常用於解決矩陣(多為稀疏矩陣)的 重複|精確 覆蓋的問題。不過一般這類問題的難點是抽出轉化關係,剩下的幾乎就是套模板

#include#include#include#include#include#include#includeusing namespace std;

typedef long long ll;

const int maxn = 65;

const int maxm = maxn*maxn*200;

const int maxd = 16;

int n, m, day;

int res[maxn];

const int mmp[6][6] =

;int tar[20][2];

struct dlx

void add(int c)

void init(int m)

l[0]=m;

r[m]=0;

sz=m+1;

memset(h,-1,sizeof(h));

}void link(int x,int y)

sz++;

}bool dfs()

add(c);

return 0;

}void cal()

}else

puts("no solution");

puts("");

}} dlx;

int edge[maxn][maxn];

int main()

for (int i = 1, b, e, da; i<= n; ++i)}}

}}

dlx.cal();

}return 0;

}

二分+dlx

#include#include#include#include#include#include#includeusing namespace std;

typedef long long ll;

const int maxn = 65;

const int maxm = maxn*maxn;

int n, m;

int vis[maxn], nlen;

ll dis[maxn][maxn], len[maxm];

inline ll mabs(ll a)

struct _point

}pt[maxn];

struct _node

r[n] = 0;

sz = n+1;

}void link(int r, int c)

++sz;

}void remv(int dx)

void resum(int dx)

int h()

}return cnt;

}void dance(int k)

mn = maxn;

for (int i = r[0]; i; i = r[i])

if (mn > s[i]) mn = s[i], dx = i;

for (int i = d[dx]; i != dx; i = d[i])

}int cal(ll mxlen)

}ans = 0;

dance(0);

return ans;

}}node;

ll solve()

return len[bg];

}int main()

return 0;

}

在一棵無向有邊權的樹上,每個節點表示男或女,可挑選任意兩點交換,是每個女的距離d之內至少有乙個男的,求交換的最小次數。

明顯同性之間沒有交換的必要,可以用dlx列舉可能的最後狀態,找出與最初狀態差別最小的

#include#include#include#include#include#include#includeusing namespace std;

const int maxn = 55;

const int maxm = maxn*maxn;

int n, m;

int vis[maxn];

int dis[maxn][maxn], boy[maxn], boys;

struct _node

r[n] = 0;

sz = n+1;

}void link(int r, int c)

++sz;

}void remv(int dx)

void resum(int dx)

int h()

}return cnt;

}void dance(int k, int p)

mn = maxn;

for (int i = r[0]; i; i = r[i])

if (mn > s[i]) mn = s[i], dx = i;

for (int i = d[dx]; i != dx; i = d[i])

}int cal()

}ans = 100000000;

dance(0, 0);

return ans>boys?-1:ans;

}}node;

void init_local()

int main()

for (int k = 1; k<= n; ++k)

for (int i = 1; i<= n; ++i)

for (int j = 1; j<= n; ++j)

dis[i][j] = min(dis[i][j], dis[i][k] + dis[k][j]);

printf("%d\n", node.cal());

}return 0;

}

比較裸的重複覆蓋問題

#include#include#include#include#include#include#includeusing namespace std;

const int maxn = 60;

const int maxm = maxn*maxn;

int n, m;

int mmp[maxn][maxn], vis[maxn];

struct _node

r[n] = 0;

sz = n+1;

}void link(int r, int c)

++sz;

}void remv(int dx)

void resum(int dx)

int h()

}return cnt;

}void dance(int k)

mn = maxn;

for (int i = r[0]; i; i = r[i])

if (mn > s[i]) mn = s[i], dx = i;

for (int i = d[dx]; i != dx; i = d[i])

}int cal()

}ans = n;

dance(0);

return ans;

}}node;

int main()

printf("%d\n", node.cal());

}return 0;

}

把每個點的覆蓋、橫 縱軸上數字的覆蓋、每個塊的覆蓋 狀態羅列出來共有 9*9*4 種狀態作為橫軸,用每個點填充數字1-9共 9*9*9 種狀態作為縱軸

#include#include#include#include#include#include#includeusing namespace std;

const int maxc = 330;

const int maxr = 735;

const int maxm = maxr*maxc;

int res[100], check[maxc], nr;

struct dlx

void add(int c)

void init(int m)

l[0]=m;

r[m]=0;

sz=m+1;

memset(h,-1,sizeof(h));

}void link(int x,int y)

sz++;

}bool dfs()

add(c);

return 0;

}} dlx;

char mmp[20][20];

int main()

else}}

if (!ans || !dlx.dfs())

printf("impossible\n");

else

for (int i = 1; i<= 9; ++i)

printf("%s\n", mmp[i]+1);}}

return 0;

}

數論合集 I

由題意可以得出將u和i都轉化為i的方法,得到公式 s 6 k 2 m 排除某些情況,s必須為偶數,所以 q s 2 q 3 k 2 n 因為q 3 0,所以q 3 a b b 1 b 2 即 3 c b 2 n 2 2 x y 2 y 1 3 x 2 y 1 3 w 因為y 0 y 1,所以 b 1...

DLX演算法模板(注釋詳解)

解決這類問題的大體思路 1 判斷所有的情況數,作為列 2 判斷所有的條件數,作為行 3 判斷每一行滿足哪些條件,可以插入1 4 判斷是精確覆蓋還是重複覆蓋 5 注意輸入輸出 精確覆蓋 struct dlx 第0個結點 表頭head 左指標指向node1,右指標指向nodem 第m個結點右指標指向he...

字尾自動機合集 I

有關字尾自動機的理論和證明各路大神的部落格多如牛毛,就不細說。貼圖太佔載入速度了,還是去看原版的解析吧 對於每個state點,father指向與該節點可接收相同字尾的節點,其表示的字串通常是當前節點表示字串的後面部分,因此state step sate father step 代表從任一字尾串起始走...