DLX。。。
一开始读错题目了。。。是要把所有正方形都消掉!!!
代码里面有两种统计正方形和火柴的方法,都值得借鉴。。Orz
发一下代码
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
const int head=0;
const int INF=10000000;
const int maxn = 1000;
const int maxd = 10000;
int cnt, res;
int mat[maxn][maxn], s[maxn], l[maxd], r[maxd], u[maxd], d[maxd], c[maxd], o[maxn], row[maxd];
bool use[maxn];
void makegragh(int &n, int &m)
{
memset(mat, 0, sizeof(mat));
//初始化mat矩阵
}
void initial(int n, int m)
{
memset(use, false, sizeof(use));
res=n+1;
int i, j, rowh;
memset(s, 0, sizeof(s));
for(i=head; i<=m; i++)
{
r[i]=(i+1)%(m+1);
l[i]=(i-1+m+1)%(m+1);
u[i]=d[i]=i;
}
cnt=m+1;
for(i=1; i<=n; i++)
{
rowh=-1;
for(j=1; j<=m; j++)
{
//printf("%d", mat[i][j]);
if(mat[i][j])
{
s[j]++;
u[cnt]=u[j];
d[u[j]]=cnt;
u[j]=cnt;
d[cnt]=j;
row[cnt]=i;
c[cnt]=j;
if(rowh==-1)
{
l[cnt]=r[cnt]=cnt;
rowh=cnt;
}
else
{
l[cnt]=l[rowh];
r[l[rowh]]=cnt;
r[cnt]=rowh;
l[rowh]=cnt;
}
cnt++;
}
}
//puts("");
}
}
void remove(int c)
{
for(int i=d[c]; i!=c; i=d[i])
{
r[l[i]]=r[i];
l[r[i]]=l[i];
}
}
void resume(int c)
{
for(int i=d[c]; i!=c; i=d[i])
r[l[i]]=l[r[i]]=i;
}
int h()
{
bool has[maxn];
memset(has, false, sizeof(has));
int ans=0;
for(int i=r[head]; i!=head; i=r[i])
if(!has[i])
{
ans++;
for(int j=d[i]; j!=i; j=d[j])
for(int k=r[j]; k!=j; k=r[k])
has[c[k]]=true;
}
return ans;
}
bool dfs(int k)
{
if(k+h()>=res)return false;//A* cut
if(r[head]==head)
{
if(k<res) res=k;
return true;
}
int ms=INF, cur=0;
for(int t=r[head]; t!=head; t=r[t])
if(s[t]<ms)
{
ms=s[t];
cur=t;
}
for(int i=d[cur]; i!=cur; i=d[i])
{
// int rr = (row[i] - 1) / 2 + 1;
// if (!use[rr]) use[rr] = true;
// else continue;
remove(i);
for(int j=r[i]; j!=i; j=r[j])
{
remove(j);
s[c[j]]--;
}
dfs(k+1);
for(int j=l[i]; j!=i; j=l[j])
{
resume(j);
s[c[j]]++;
}
// use[rr] = false;
resume(i);
}
return false;
}
const int N=10;
int stick[2*N*(N+1)+N][N*N];/*
void makestick(int n)
{
for (int i=1;i<=2*n*(n+1);++i)
{
if (i<=n)
{
stick[i][0]=1;
stick[i][1]=i;
}
else if (i>=2*n*(n+1)-n+1)
{
stick[i][0]=1;
stick[i][1]=n*n-2*n*(n+1)+i;
}
else if (i % (2*n+1)==n+1)
{
stick[i][0]=1;
stick[i][1]=((i)/(2*n+1))*n+1;
}
else if (i % (2*n+1)==0)
{
stick[i][0]=1;
stick[i][1]=(i/(2*n+1))*n;
}
else if (i % (2*n+1)>n+1)
{
stick[i][0]=2;
stick[i][1]=(i/(2*n+1))*n+i%(2*n+1)-n-1;
stick[i][2]=(i/(2*n+1))*n+i%(2*n+1)-n;
}
else
{
stick[i][0]=2;
stick[i][1]=(i/(2*n+1)-1)*n+i%(2*n+1);
stick[i][2]=(i/(2*n+1)-1)*n+i%(2*n+1)+n;
}
}/*
for (int i=1;i<=2*n*(n+1);++i)
{
printf("%d--%d:",i,stick[i][0]);
for (int j=1;j<=stick[i][0];++j)
printf(" %d",stick[i][j]);
printf("\n");
}
}
*/
int NumOfSq;
void makestick(int n)
{
memset(stick,0,sizeof(stick));
NumOfSq=0;int ss;
for (int c=1;c<=n;++c)
{
for (int i=1;i<=n-c+1;++i)
{
for (int j=1;j<=n-c+1;++j)
{
++NumOfSq;
//Up
ss=(i-1)*(2*n+1)+j;
for (int p=0;p<c;++p)
{
++stick[ss+p][0];
stick[ss+p][stick[ss+p][0]]=NumOfSq;
}
//Left
ss=(i-1)*(2*n+1)+j+n;
for (int p=0;p<c;++p)
{
stick[ss+p*(2*n+1)][++stick[ss+p*(2*n+1)][0]]=NumOfSq;
}
//Right
ss=(i-1)*(2*n+1)+j+c+n;
for (int p=0;p<c;++p)
{
stick[ss+p*(2*n+1)][++stick[ss+p*(2*n+1)][0]]=NumOfSq;
}
//Down
ss=(i-1+c)*(2*n+1)+j;
for (int p=0;p<c;++p)
{
stick[ss+p][++stick[ss+p][0]]=NumOfSq;
}
}
}
}
/*
for (int i=1;i<=2*n*(n+1);++i)
{
printf("%d--%d:",i,stick[i][0]);
for (int j=1;j<=stick[i][0];++j)
printf(" %d",stick[i][j]);
printf("\n");
}
*/
}
int n,m,M;
bool lstsq[N*N*2+N];
bool lststick[2*N*(N+1)+N];
int sq[N*N*2+N];
int sqnum[N*N*2+N];
int main()
{
int t;
scanf("%d",&t);
while (t--)
{
memset(sqnum,0,sizeof(sqnum));
memset(mat,0,sizeof(mat));
memset(lstsq,0,sizeof(lstsq));
memset(lststick,0,sizeof(lststick));
memset(sq,0,sizeof(sq));
scanf("%d%d",&n,&m);
makestick(n);
int rline;
while (m--)
{
int st;
scanf("%d",&st);
lststick[st]=1;
for (int i=1;i<=stick[st][0];++i)
lstsq[stick[st][i]]=1;
}
sq[0]=0;
for (int i=1;i<=NumOfSq;++i)
{
if (lstsq[i]) continue;
++sq[0];
sq[sq[0]]=i;
sqnum[i]=sq[0];
}
rline=0;
for (int i=1;i<=2*n*(n+1);++i)
{
if (lststick[i]) continue;
++rline;
for (int j=1;j<=stick[i][0];++j)
{
if (lstsq[stick[i][j]]) continue;
mat[rline][sqnum[stick[i][j]]]=1;
}
}
initial(rline,sq[0]);
dfs(0);
printf("%d\n",res);
}
}