Treasure Map ZOJ - 3209

2 篇文章 0 订阅

参考https://blog.csdn.net/qq_35479641/article/details/51887172该题的DLX模板

 

#include <iostream>
#include <cstdio>

using namespace std;

const int maxnode=100010;//最大节点数
const int maxm=1010;//最大列数
const int maxn=1010;//最大行数
const int inf = 0x3f3f3f3f;

class dlx {
	public:
		int n,m,size;

		int R[maxnode],L[maxnode],U[maxnode],D[maxnode],col[maxnode],H[maxn],row[maxnode],S[maxm];

		//表示最后选中的行的数量,ans记录答案
		int res,ans[maxn];

		void init(int x,int y) {
			n=x;
			m=y;
			res = inf;
			int i;

			for(i=0; i<=m; i++) {
				S[i]=0;
				U[i]=i;
				D[i]=i;
				L[i]=i-1;
				R[i]=i+1;
			}
			L[0]=m;
			R[m]=0;

			size=m;

			for(i=0; i<=n; i++) {
				H[i]=-1;
			}
		}

		void link(int r,int c) {
			size++;
			col[size]=c;
			row[size]=r;
			
			S[col[size]]++;
			

			U[size]=c;
			D[size]=D[c];
			U[D[c]]=size;
			D[c]=size;

			if(H[r]<0) {
				H[r]=L[size]=R[size]=size;
			}
			else {
				R[size]=R[H[r]];
				L[size]=H[r];
				L[R[H[r]]]=size;
				R[H[r]]=size;
			}
		}

		void remove(int c) {
			R[L[c]]=R[c];
			L[R[c]]=L[c];
			int x,y;
			for(x=D[c]; x!=c; x=D[x]) {
				for(y=R[x]; y!=x; y=R[y]) {
					D[U[y]]=D[y];
					U[D[y]]=U[y];
					S[col[y]]--;
				}
			}
		}

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

		void dance(int cnt) { 
			//当原点的右边结点是自己时,所有的已经全部删除完毕,符合条件
			if(R[0]==0) {
				res=min(res, cnt);

				return;
			}
			int cur;
			cur=R[0];
			for(int i=cur; i!=0; i=R[i]) {
				if(S[cur]>S[i]) {
					cur=i;
				}
			}
			remove(cur);
			int i,j;

			for(i=D[cur]; i!=cur; i=D[i]) {
				for(j=R[i]; j!=i; j=R[j]) {
					remove(col[j]);
				}
				dance(cnt+1);

				for(j=L[i]; j!=i; j=L[j]) {
					resume(col[j]);
				}
			}
			resume(cur);
			return;
		}
};

dlx test;

int main() {
	int nn,mm, k, T;

	scanf("%d", &T);

	while(T--) {
		scanf("%d%d%d", &nn, &mm, &k);
		test.init(k,nn*mm);
		int cn=0, j, x1, y1, x2, y2;
		for(int i=1; i<=k; i++) {

			scanf("%d%d%d%d", &x1, &y1, &x2, &y2);

			for(int j=x1; j<x2; j++) {
				for(int k=y1+1; k<=y2; k++)
					test.link(i, j*mm+k);
			}
		}
		test.dance(0);
		printf("%d", test.res == inf ? -1 : test.res);
		printf("\n");
	}
	return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值