POJ 1084

WA了好久,第一次用重覆盖的模型做题。感觉这题有个陷阱,那就是当去掉某些边后,若因为这个边去掉而被破环的正方形还存在,那么就会造成覆盖不完全,WA.

所以,在去掉边后,必定有些正方形是不存在的,须重新计算。另外,计算一个正方形有哪些边也很困难。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

const int Maxn=100;
const int Maxr=100;
const int Maxnode=10000;
const int inf=(1<<30);

bool vis[Maxn];
bool ls[Maxr][Maxn];
int L[Maxnode], R[Maxnode], D[Maxnode], U[Maxnode], C[Maxnode];
int S[Maxn], H[Maxr], size;
	//²»ÐèÒªSÓò
void Link(int r, int c)
{
    S[c]++; C[size]=c;
    U[size]=U[c]; D[U[c]]=size;
    D[size]=c; U[c]=size;
    if(H[r]==-1) H[r]=L[size]=R[size]=size;
    else {
        L[size]=L[H[r]]; R[L[H[r]]]=size;
        R[size]=H[r]; L[H[r]]=size;
    }
    size++;
}
void remove(int c){
    for (int i=D[c]; i!=c; i=D[i])
        L[R[i]]=L[i], R[L[i]]=R[i];
}
void resume(int c){
    for (int i=U[c]; i!=c; i=U[i])
        L[R[i]]=R[L[i]]=i;
}
int h(){	//Óþ«È·¸²¸ÇÈ¥¹ÀËã¼ôÖ¦
    int ret=0;
    bool vist[Maxn];
    memset (vist, false, sizeof(vist));
    for (int i=R[0]; i; i=R[i])
    {
        if(vist[i])continue;
        ret++;
        vist[i]=true;
        for (int j=D[i]; j!=i; j=D[j])
            for (int k=R[j]; k!=j; k=R[k])
                vist[C[k]]=true;
    }
    return ret;
}

int ans;
void Dance(int k){                //¸ù¾Ý¾ßÌåÎÊÌâÑ¡ÔñÏÞÖÆËÑË÷Éî¶È»òÖ±½ÓÇó½â¡£
    if(k+h()>=ans) return;
    if(!R[0]){
        if(k<ans)ans=k;
        return;
    }
    int c=R[0];
    for (int i=R[0]; i; i=R[i])
        if(S[i]<S[c])c=i;
    for (int i=D[c]; i!=c; i=D[i]){
        remove(i);
        for (int j=R[i]; j!=i; j=R[j])
            remove(j);
        Dance(k+1);
        for (int j=L[i]; j!=i; j=L[j])
            resume(j);
        resume(i);
    }
    return ;
}

void initL(int x){	//col is 1~x,row start from 1
    for (int i=0; i<=x; ++i){
        S[i]=0;
        D[i]=U[i]=i;
        L[i+1]=i; R[i]=i+1;
    }	//¶ÔÁбíÍ·³õʼ»¯
    R[x]=0;
    size=x+1;	//ÕæÕýµÄÔªËØ´Óm+1¿ªÊ¼
    memset (H, -1, sizeof(H));
    ans=inf;
    	//markÿ¸öλÖõÄÃû×Ö
}

bool check(int i,int j,int si,int n){
	for(int k=0;k<si;k++){
		if(vis[(i-1)*(2*n+1)+j+k]) return false;
 		if(vis[(i-1+si)*(2*n+1)+j+k]) return false;
  		if(vis[i*n+(i-1)*(n+1)+j+k*(2*n+1)]) return false;
   		if(vis[i*n+(i-1)*(n+1)+j+k*(2*n+1)+si]) return false;
   	}
   	return true;
}

int main(){
	int kase,n; int sof,tmp,tt,c;
	scanf("%d",&kase);
	while(kase--){
	//	sof=0;
		scanf("%d",&n);
	//	initL(sof);
		scanf("%d",&tt);
		memset(vis,false,sizeof(vis));
		for(int i=1;i<=tt;i++){
			scanf("%d",&tmp);
			vis[tmp]=true;
		}
		memset(ls,false,sizeof(ls));
		c=1;
	    for(int si=1;si<=n;si++){
			for(int i=1;i<=n-si+1;i++){
   				for(int j=1;j<=n-si+1;j++){
   					if(check(i,j,si,n)){
					  for(int k=0;k<si;k++){
                    	ls[(i-1)*(2*n+1)+j+k][c]=true;
                     	ls[(i-1+si)*(2*n+1)+j+k][c]=true;
                     	ls[i*n+(i-1)*(n+1)+j+k*(2*n+1)][c]=true;
                     	ls[i*n+(i-1)*(n+1)+j+k*(2*n+1)+si][c]=true;
 					  }
 					   	c++;
   					}
             	}
         	}
     	}
     	initL(c-1);
     	for(int i=1;i<=2*(n)*(n+1);i++){
     		for(int j=1;j<c;j++)
     		if(ls[i][j])
     		Link(i,j);
     	}
     	Dance(0);
     	printf("%d\n",ans);
	}
	return 0;
}

  

时间: 2024-11-05 13:45:10

POJ 1084的相关文章

poj 1084 Square Destroyer dlx解重复覆盖

分析: 将问题转化为重复覆盖问题,DancingLink解决. 代码: //poj 1084 //sep9 #include <iostream> using namespace std; const int maxN=10024; const int maxL=128; int L[maxN],R[maxN],U[maxN],D[maxN]; int C[maxN],H[maxN]; int S[maxN],A[maxN],X[maxN]; bool makeup[maxL][maxL];

【POJ 1084】 Square Destroyer

[题目链接] http://poj.org/problem?id=1084 [算法] 迭代加深 [代码] #include <algorithm> #include <bitset> #include <cctype> #include <cerrno> #include <clocale> #include <cmath> #include <complex> #include <cstdio> #inclu

poj 1084 Brainman

题目链接:http://poj.org/problem?id=1804 思路: 序列的逆序数即为交换次数,所以求出该序列的逆序数即可. 根据分治法思想,序列分为两个大小相等的两部分,分别求子序列的逆序数:对于右子序列中的每一个数,求出左序列中大于它的数的数目,计算的和即为解. 另外,使用Merge排序时,可以很容易求得对于右子序列中的每一个数,左序列中大于它的数的数目. 代码: #include <stdio.h> #include <limits.h> long long Cou

[DLX重复覆盖] poj 1084 Square Destroyer

题意: n*n的矩形阵(n<=5),由2*n*(n+1)根火柴构成,那么其中会有很多诸如边长为1,为2...为n的正方形,现在可以拿走一些火柴,那么就会有一些正方形被破坏掉. 求在已经拿走一些火柴的情况下,还需要拿走至少多少根火柴可以把所有的正方形都破坏掉. 思路: 对于每个位置遍历所有可能的边长,确定这个边长下的正方形的边对应的都是数字几,并且把正方形从1开始编号. 然后根据编号,把正方形和数字建边记录方便下面建图. 然后以火柴棍为行,正方形为列,建立dancing link 然后求解. 这里

[DLX反复覆盖] poj 1084 Square Destroyer

题意: n*n的矩形阵(n<=5),由2*n*(n+1)根火柴构成,那么当中会有非常多诸如边长为1,为2...为n的正方形,如今能够拿走一些火柴,那么就会有一些正方形被破坏掉. 求在已经拿走一些火柴的情况下.还须要拿走至少多少根火柴能够把全部的正方形都破坏掉. 思路: 对于每一个位置遍历全部可能的边长,确定这个边长下的正方形的边相应的都是数字几,而且把正方形从1開始编号. 然后依据编号,把正方形和数字建边记录方便以下建图. 然后以火柴棍为行,正方形为列,建立dancing link 然后求解.

(中等) POJ 1084 Square Destroyer , DLX+可重复覆盖。

Description The left figure below shows a complete 3*3 grid made with 2*(3*4) (=24) matchsticks. The lengths of all matchsticks are one. You can find many squares of different sizes in the grid. The size of a square is the length of its side. In the

POJ 1084 Square Destroyer【舞蹈链】【重复覆盖】

建模很容易就能说清楚,但我一直想不出来. 要问为什么的话可能是因为这题要先预处理出来所有正方形,而我没做过要预处理的舞蹈链的题.所以想不到. 那就是预处理出来所有正方形,用一个long long来表示一个正方形,这个正方形有没有包含id这条边就用 (1<<id)&num判断.那怎么预处理所有正方形呢,枚举边长1-n的正方形,然后再枚举这个正方形左上方的顶点就能做出来. 然后就能建模了,火柴是行,所有按现有火柴能拼出来的正方形是列,与其说是精准覆盖倒也可以说是全部破坏. http://e

Dancing Links [Kuangbin带你飞] 模版及题解

学习资料: http://www.cnblogs.com/grenet/p/3145800.html http://blog.csdn.net/mu399/article/details/7627862 2份模版 第一份精确覆盖 from POJ 3074 const int N = 9; const int MAXN = N * N * N + 10; const int MAXM = N * N * 4 + 10; const int MAXNODE = MAXN * 4 + MAXM +

wewe

BFS广搜题目有时间一个个做下来 2009-12-29 15:09 1574人阅读 评论(1) 收藏 举报 图形graphc优化存储游戏 有时间要去做做这些题目,所以从他人空间copy过来了,谢谢那位大虾啦. pku 1175 Starry Night 题目地址:http://acm.pku.edu.cn/JudgeOnline/problem?id=1175 解法:BFS,要注意的是如何判断图形是一样的,我的做法就是计算每两个点的距离之和. 看:http://hi.baidu.com/doxi