DLX

说实话这么奇怪十字的链表结构还能在里面删来恢复,按各种顺序和套路以致把时间复杂度减下来,果然是Knuth !
主要是计算最小列从n*m变成了m了,这里m是指下面代码的mm

#include <cstdio>
#include <memory>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <vector>
#include <cassert>
#include <string>
#include <ctime>
#include <map>
#include <queue>
#include <algorithm>
#include <iostream>
#include <cassert>
#include <iomanip> 
#include <set>
#include <iterator>  
using namespace std;
#define REP(i,n) for(int i=0;i<n;i++)
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define req(i,a,b) for(int i=a;i>=b;i--)
#define rp(i,a) for(int i=head[a];i+1;i=edge[i].next)
#define cl(a,b) memset(a,b,sizeof a);
#define ll long long
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define mod 10007
const int inf = ~0u >> 2;
const ll INF = (1LL << 62) - 1;
double eps = 1e-12;
const int N = 505 + 5;
const int M = 35*35;
int s[N];

int n, m, k;
//int a[M][M];
int b[M*N+M];
class DLX {
private:
	const static int maxn = M*N+M;
public:
	int l[maxn], r[maxn], u[maxn], d[maxn], s[M];
	int row[maxn],col[maxn],head[N];
	int sz = 0;
	void init(int n,int mm) {
		cnt = 0;
		ans = inf;
		level = 0;
		sz = 0;
		for (int j = 0; j <= mm; j++)
		{
			row[j] = 0;
			col[j] = j;
			s[j] = 0;
			l[j] = j - 1;
			r[j] = j + 1;
			u[j] = d[j] = j;
			sz++;
		}
		sz--;
		l[0] = mm;
		r[mm] = 0;
		for (int i = 1; i <= n; i++)
			head[i] = -1;
	}
	void remove(int y) {//y is column index
		r[l[y]] = r[y];
		l[r[y]] = l[y];
		for (int i = d[y]; i != y; i = d[i]) {
			for (int j = r[i]; j != i; j = r[j]) {
				d[u[j]] = d[j];
				u[d[j]] = u[j];
				s[col[j]]--;
			}
		}
	}
	void resume(int y) {//y is column index
		for (int i = u[y]; i != y; i = u[i]) {
			for (int j = l[i]; j != i; j = l[j]) {
				d[u[j]] = j;
				u[d[j]] = j;
				s[col[j]]++;
			}
		}
		l[r[y]] = y;
		r[l[y]] = y;
	}
	void link(int rowIndex, int colIndex) {
		col[++sz] = colIndex;
		s[colIndex]++;
		d[sz] = d[colIndex];
		u[sz] = colIndex;
		u[d[sz]] = sz;
		d[u[sz]] = sz;
		if (head[rowIndex] == -1)
		{
			l[sz] = r[sz] = sz;
			head[rowIndex] = sz;
		}
		else {
			l[sz] = head[rowIndex];
			r[sz] = r[head[rowIndex]];
			l[r[sz]] = sz;
			r[l[sz]] = sz;
		}
		
	}
	bool dance() {
		if (r[0] == 0) {
			return true;
		}
		int minum = r[0];
		for (int i = r[0]; i != 0; i = r[i]) {
			if (s[i] < s[minum])
				minum = i;
		}
		if (s[minum] == 0) {
			return false;
		}

		level++;
		if (level >= ans)
		{
			level--;
			return false;
		}
		remove(minum);

		for (int i = d[minum]; i != minum; i = d[i]) {
			for (int j = r[i]; j != i; j = r[j]) {
				remove(col[j]);
			}
			bool flag = dance();
			for (int j = l[i]; j != i; j = l[j]) {
				resume(col[j]);
			}
			if (flag||level>=ans) {
				cnt++;
				ans = min(ans, level);
				break;
			}
		}

		resume(minum);
		level--;

		return false;
	}
	int getAns() {
		return ans;
	}
private:
	int cnt = 0;
	int ans = inf;
	int level = 0;
}dlx;
int main() {
	int t;
	//std::ios::sync_with_stdio(false);
	scanf("%d", &t);
	while (t--) {
		scanf("%d%d%d", &n, &m, &k);
		int mm = n*m;
		dlx.init(k,mm);
		for (int p = 1; p <= k; p++) {
			int x, y, xx, yy;
			scanf("%d%d%d%d", &x, &y, &xx, &yy);
			
			for (int i = x + 1; i <= xx; i++)
			{
				for (int j = y + 1; j <= yy; j++) {
					dlx.link(p, (i - 1)*m + j);
				}
			}
		}
		dlx.dance();
		printf("%d
", dlx.getAns()==inf?-1:dlx.getAns());
	}
	return 0;
}
原文地址:https://www.cnblogs.com/HaibaraAi/p/6516073.html