破坏正方形

破坏正方形

首先计算出火柴总数正方形总数

考虑横着的火柴有 \(n+1\) 行,每行有 \(n\) 根,竖着的同理(旋转 \(90°\)),所以一共有 \(2n(n+1)\) 根火柴。

边长为 \(1\) 的正方形有 \(n^2\) 个,\(2,(n-1)^2;3,(n-2)^2;\dots;n,1^2\)\(\sum_{i=1}^n i^2=\dfrac{n(n+1)(2n+1)}{6}\) 。所以共有这么多正方形。

然后分析题目。这是一个重复覆盖问题(不存在多项式做法,经典做法:Dacing Links)。可以抽象出一个二维矩阵,每一列代表所有的正方形,每一行代表每一根火柴,\((i,j)\) 表示第 \(i\) 根火柴是否是第 \(j\) 个正方形的边。这道题就用朴素做法。

首先搜索顺序很简单,就按照没有被破坏的正方形进行搜索,可以按照从小到大的边长,因为小的边长分支会少一些(之前许多搜索题目的共性),枚举边上的火柴即可。估价函数根据 Dacing Links 中的,是枚举每个正方形,如果是完整的,就删除所有边,并算作删除一次。显然这个估价是正确的。

还有就是如果快速求出某个正方形的边。左右相差 \(1\) 根,上下则跨过 \(n\)\(n+1\) 竖,共 \(2n+1\) 根。

#include<bits/stdc++.h>
using namespace std;
#define Ls(i,l,r) for(int i=l;i<r;++i)
#define Rs(i,l,r) for(int i=r;i>l;--i)
#define L(i,l) for(int i=0;i<l;++i)
#define wh(i) while(i--)
const int N=61;
int T,n,m;
vector<int>s[N];
bool st[N];
bool check(int x){
    for(int v:s[x])
        if(st[v])return 0;
    return 1;
}
int f(){
    static bool state[N];
    memcpy(state,st,sizeof st);
    int cnt=0;
    L(i, m){
        if(check(i)){
            ++cnt;
            for(int v:s[i])st[v]=1;
        }
    }
    memcpy(st,state,sizeof st);
    return cnt;
}
bool dfs(int dep,int max_dep){
    if(dep+f()>max_dep)return 0;
    L(i, m){
        if(check(i)){
            for(int v:s[i]){
                st[v]=1;
                if(dfs(dep+1,max_dep))return 1;
                st[v]=0;
            }
            return 0;
        }
    }
    return 1;
}
int main(){
    // freopen("1.in","r",stdin);
    // freopen("1.out","w",stdout);
    // ios::sync_with_stdio(0);
    // cin.tie(0);
    // cout.tie(0);
    scanf("%d",&T);
    wh(T){
        memset(st,0,sizeof st);
        m=0;
        scanf("%d",&n);
        int d=2*n+1;
        Ls(len, 1, n+1)
            Ls(a, 1, n+2-len)
                Ls(b, 1, n+2-len){
                    auto &sq=s[m++];
                    sq.clear();
                    L(i, len){
                        sq.push_back((a-1)*d+b+i);
                        sq.push_back((a-1)*d+b+i+len*d);
                        sq.push_back((a-1)*d+b+n+i*d);
                        sq.push_back((a-1)*d+b+n+i*d+len);
                    }
                }
        int k;
        scanf("%d",&k);
        wh(k){
            int x;
            scanf("%d",&x);
            st[x]=1;
        }
        int dep=0;
        while(!dfs(0, dep))++dep;
        printf("%d\n",dep);
    }
    return 0;
}
posted @ 2023-05-13 20:06  wscqwq  阅读(12)  评论(0编辑  收藏  举报