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 代表從任一字尾串起始走...