poj1084Square Destroyer(LDX解重复覆盖)

题目请戳这里

题目大意:给一个n*n的用单位长度的木棍拼起来的网格图,给每个木棍按图示编号,编号范围1~2*n*(n+1).现在已知图中已经去掉了k个木棍,求还要至少去掉几根木棍能使网格图中不存在正方形.即破坏图中所有的正方形.n不超过5.

题目分析:n太小了啦,直接爆搜!dancing links优化之.将之转化成一个重复覆盖的模型.

n*n的完全网格图中存在n*(n+1)*(2*n+1)/6个正方形.给每一个编号,然后小木棍的编号图中给了,就按那个来.然后小木棍为行,正方形为列,建图.

注意题目已经给定的k个木棍要去掉.首先那k个木棍覆盖的正方形是不用建图的,然后那k个表头也要删掉.

然后关于木棍编号破坏的正方形的关系.好像很复杂的样子,不过因为n太小了,然后我就打表了大笑..不过好难数,数了一晚上....哭

正方形编号从1~n*(n+1)*(2*n+1)/6,顺序按边长递增从左上角到右下角.

详情请见代码:

#include <iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 6;
const int M = 4000;//3300
const int NM = 56;//最大正方形个数
int n,K,num,ans;
int h[M],s[M],u[M],d[M],l[M],r[M],col[M];
bool flag[NM],vis[NM];
int stk[NM];
int table[5][61][NM] = {
{
    {0},{1,1},{1,1},{1,1},{1,1},
},
{   {0},{2,1,5},{2,2,5},{2,1,5},{2,1,2},{2,2,5},{2,1,3},
    {2,2,4},{2,3,5},{2,3,4},{2,4,5},{2,3,5},{2,4,5},
},
{   {0},{3,1,10,14},{4,2,10,11,14},{3,3,11,14},{3,1,10,14},
    {3,1,2,11},{3,2,3,10},{3,3,11,14},{3,1,4,12},{4,2,5,12,13},
    {3,3,6,13},{4,4,10,12,14},{4,4,5,11,13},{4,5,6,10,12},
    {4,6,11,13,14},{3,4,7,10},{4,5,8,10,11},{3,6,9,11},
    {3,7,12,14},{3,7,8,13},{3,8,9,12},{3,9,13,14},
    {3,7,12,14},{4,8,12,13,14},{3,9,13,14},
},
{   {0},{4,1,17,26,30},{6,2,17,18,26,27,30},{6,3,18,19,26,27,30},{4,4,19,27,30},
    {4,1,17,26,30},{4,1,2,18,27},{4,2,3,17,19},{4,3,4,18,26},{4,4,19,27,30},
    {4,1,5,20,28},{5,2,6,20,21,29},{5,3,7,21,22,28},{4,4,8,22,29},
    {6,5,17,20,26,28,30},{6,5,6,18,21,27,29},{6,6,7,17,19,20,22},{6,7,8,18,21,26,28},{6,8,19,22,27,29,30},
    {4,5,9,17,23},{6,6,10,17,18,23,24},{6,7,11,18,19,24,25},{4,8,12,19,25},
    {6,9,20,23,26,28,30},{6,9,10,21,24,27,29},{6,10,11,20,22,23,25},{6,11,12,21,24,26,28},{6,12,22,25,27,29,30},
    {4,9,13,20,26},{5,10,14,20,21,27},{5,11,15,21,22,26},{4,12,16,22,27},
    {4,13,23,28,30},{4,13,14,24,29},{4,14,15,23,25},{4,15,16,24,28},{4,16,25,29,30},
    {4,13,23,28,30},{6,14,23,24,28,29,30},{6,15,24,25,28,29,30},{4,16,25,29,30},
},
{   {0},
    {5,1,26,42,51,55},{8,2,26,27,43,44,51,52,55},{9,3,27,28,42,43,44,51,52,55},{8,6,4,28,29,43,44,51,52,55},{5,5,29,44,52,55},
    {5,1,26,42,51,55},{5,1,2,27,43,52},{5,2,3,26,28,44},{5,3,4,27,29,42},{5,4,5,28,43,51},{5,5,29,44,52,55},
    {5,1,6,30,45,53},{8,2,7,30,31,45,46,53,54},{9,3,8,31,32,45,46,47,53,54},{8,4,9,32,33,46,47,53,54},{5,5,10,33,47,54},
    {8,6,26,30,42,45,51,53,55},{8,6,7,27,31,43,46,52,54},{8,7,8,26,28,30,32,44,47},{8,8,9,27,29,31,33,42,45},{8,9,10,28,32,43,46,51,53},{8,10,29,33,44,47,52,54,55},
    {5,6,11,26,34,48},{8,7,12,26,27,34,35,48,49},{9,8,13,27,28,35,36,48,49,50},{8,9,14,28,29,36,37,49,50},{5,10,15,29,37,50},
    {9,11,30,34,42,45,48,51,53,55},{9,11,12,31,35,43,46,49,52,54},{9,12,13,30,32,34,36,44,47,50},{9,13,14,31,33,35,37,42,45,48},{9,14,15,32,36,43,46,49,51,53},{9,15,33,37,44,47,50,52,54,55},
    {5,11,16,30,38,42},{8,12,17,30,31,38,39,42,43},{9,13,18,31,32,39,40,42,43,44},{8,14,19,32,33,40,41,43,44},{5,15,20,33,41,44},
    {8,16,34,38,45,48,51,53,55},{8,16,17,35,39,46,49,52,54},{8,17,18,34,36,38,40,47,51},{8,18,19,35,37,39,41,45,48},{8,19,20,36,40,46,49,51,53},{8,20,37,41,47,50,52,54,55},
    {5,16,21,34,45,51},{8,17,22,34,35,45,46,51,52},{9,18,23,35,36,45,46,47,51,52},{8,19,24,36,37,46,47,51,52},{5,20,25,37,47,52},
    {5,21,38,48,53,55},{5,21,22,39,49,54},{5,22,23,38,40,50},{5,23,24,39,41,48},{5,24,25,40,49,53},{5,25,41,50,54,55},
    {5,21,38,48,53,55},{8,22,38,39,48,49,53,54,55},{9,23,39,40,48,49,50,53,54,55},{8,24,40,41,49,50,53,54,55},{5,25,41,50,54,55},
}
};

void init()
{
    int i,c;
    memset(h,0,sizeof(h));
    memset(s,0,sizeof(s));
    c = n * (n + 1) * (2 * n + 1)/6;
    for(i = 0;i <= c;i ++)
    {
        u[i] = d[i] = i;
        l[i] = (i + c)%(c + 1);
        r[i] = (i + 1)%(c + 1);
    }
    num = c + 1;
}
void ins(int i,int j)
{
    if(h[i])
    {
        r[num] = h[i];
        l[num] = l[h[i]];
        l[r[num]] = r[l[num]] = num;
    }
    else
    {
        h[i] = num;
        l[num] = r[num] = num;
    }
    s[j] ++;
    u[num] = u[j];
    d[num] = j;
    d[u[j]] = num;
    u[j] = num;
    col[num] = j;
    num ++;
}
void del(int c)
{
    for(int i = d[c];i != c;i = d[i])
        l[r[i]] = l[i],r[l[i]] = r[i];
}
void recover(int c)
{
    for(int i = u[c];i != c;i = u[i])
        l[r[i]] = r[l[i]] = i;
}
int A()
{
    int i,j,k,ret;
    ret = 0;
    memset(vis,false,sizeof(vis));
    for(i = r[0];i;i = r[i])
    {
        if(vis[i] == false)
        {
            ret ++;
            vis[i] = true;
            for(j = d[i];j != i;j = d[j])
                for(k = r[j];j != k;k = r[k])
                    vis[col[k]] = true;
        }
    }
    return ret;
}
void dfs(int k)
{
    if(k + A() >= ans)
        return;
    if(!r[0])
    {
        ans = min(ans,k);
        return ;
    }
    int mn = M;
    int c,i,j;
    for(i = r[0];i;i = r[i])
    {
        if(s[i] < mn)
        {
            mn = s[i];
            c = i;
        }
    }
    for(i = d[c];i != c;i = d[i])
    {
        del(i);
        for(j = r[i];j != i;j = r[j])
            del(j);
        dfs(k + 1);
        for(j = l[i];j != i;j = l[j])
            recover(j);
        recover(i);
    }
}

void build()
{
    scanf("%d",&n);
    memset(flag,false,sizeof(flag));

    scanf("%d",&K);
    int i,j;
    for(i = 1;i <= K;i ++)
    {
        scanf("%d",&stk[i]);
        for(j = 1;j <= table[n - 1][stk[i]][0];j ++)
            flag[table[n - 1][stk[i]][j]] = true;
    }
    init();
    for(i = 1;i <= (n + 1) * n * 2;i ++)
    {
        for(j = 1;j <= table[n - 1][i][0];j ++)
            if(flag[table[n - 1][i][j]] == false)
                ins(i,table[n - 1][i][j]);
    }
    int nmgb = 0;
    for(i = 1;i <= n * (n + 1) * (n * 2 + 1)/6;i ++)
        if(flag[i])
            l[r[i]] = l[i],r[l[i]] = r[i];
}
void fuck()
{
    ans = M;
    dfs(0);
    printf("%d\n",ans);
}
int main()
{
    int t;scanf("%d",&t);
    while(t --)
    {
        build();
        fuck();
    }
    return 0;
}
//244K	0MS



你可能感兴趣的:(搜索)