首先,没写N皇后的建议先把N皇后给做了,题解在这里:http://blog.csdn.net/night_raven/article/details/19146023
N*N的棋盘放K个皇后,0<=K<=n*n..之前一直没想好K皇后怎么转化成精确覆盖问题,因为它行列都不一定全部覆盖,而DLX在搜的时候,它是按照一个固定的顺序,一行一行的删除的,后来想了想,枚举到一行的时候,只要能添加一种“不放置”的选择,那么在搜完K行的时候得到的就是一组解。实现的话,建表和N皇后一样,搜索的时候有些变动,不放置的选择对应一个假删除,就是只把矩阵中对应棋盘上该行的一列的列表头删除而矩阵中的内容不变,这样既没有在这这里放置皇后,又避免了下一次枚举到这个不放置的行。虽说写是写完了,交上去居然T掉了=...反正一共就10*10种情况,果断打表...打出所有的情况也就用了十几秒的时间,一定是SGU时间卡的太死了= =.....
打表的程序:
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
using namespace std;
typedef long long ll;
const int tt=60;
const int maxr=tt*tt;
const int maxc=6*tt;
const int maxn=maxr*maxc;
int col[maxn],row[maxn],R[maxn],L[maxn],U[maxn],D[maxn];
int ct[10];
int a[55];
int sp;
int head[tt][tt];
int S[maxr];
int size,mRow;
int n,m,k;
struct ANS
{
int x,y;
}ans[maxr];
int anss[330];
int st[maxr];
struct DLX
{
void resume(int c)
{
L[R[c]]=c;
R[L[c]]=c;
for (int i=U[c]; i!=c; i=U[i])
for (int j=L[i]; j!=i; j=L[j])
{
U[D[j]]=j;
D[U[j]]=j;
++S[col[j]];
}
}
void remove(int c)
{
L[R[c]]=L[c];
R[L[c]]=R[c];
for (int i=D[c]; i!=c; i=D[i])
for (int j=R[i]; j!=i; j=R[j])
{
U[D[j]]=U[j];
D[U[j]]=D[j];
--S[col[j]];
}
}
void init(int m)
{
for (int i=1; i<=m; i++)
{
L[i]=i-1;
R[i]=i+1;
U[i]=D[i]=i;
S[i]=0;
col[i]=i;
row[i]=0;
}
L[0]=m;
R[0]=1;
R[m]=0;
U[0]=D[0]=0;
size=m;
mRow=0;
}
int makehead(int c)
{
size++;
S[c]++;
col[size]=c;
row[size]=mRow;
L[size]=R[size]=size;
U[size]=c;
D[size]=D[c];
U[D[size]]=D[U[size]]=size;
return size;
}
void addcol(int id,int c)
{
size++;
S[c]++;
col[size]=c;
row[size]=mRow;
L[size]=id;
R[size]=R[id];
L[R[size]]=R[L[size]]=size;
U[size]=c;
D[size]=D[c];
U[D[size]]=D[U[size]]=size;
}
void addrow(int i,int j)
{
int id;
mRow++;
ans[mRow].x=i;
ans[mRow].y=j;
id=makehead(i+ct[0]);
head[i][j]=id;
addcol(id,j+ct[1]);
addcol(id,i+j+ct[2]);
addcol(id,i-j+n-1+ct[3]);
}
bool dfs(int k)
{
if (k==m)
{
// for (int i=0; i<k; i++)
// if (a[ans[st[i]].x]==0)anss[ans[st[i]].x]=ans[st[i]].y;
// for (int i=0; i<k; i++)
// cout<<ans[st[i]].x+1<<" "<<ans[st[i]].y+1<<endl;
sp++;
// cout<<anss[0]+1;
// for (int i=1; i<n; i++)
// cout<<" "<<anss[i]+1;
// cout<<endl;
// sp++;
return true;
}
int c=0;
int minn=(1<<28);
for (int i=R[0]; i<=n; i=R[i])
{
if (!S[i]) continue;
if (S[i]<minn)
{
minn=S[i];
c=i;
}
}
if (c==0) return false;
for (int ii=0; ii<2; ii++)
if (ii==0)
{
remove(c);
for (int i=D[c]; i!=c; i=D[i])
{
st[k]=row[i];
for (int j=R[i]; j!=i; j=R[j]) remove(col[j]);
dfs(k+1);
for (int j=L[i]; j!=i; j=L[j]) resume(col[j]);
}
resume(c);
}
else
{
L[R[c]]=L[c];
R[L[c]]=R[c];
dfs(k);
L[R[c]]=c;
R[L[c]]=c;
}
return false;
}
}dlx;
int main()
{
// freopen("in.txt","r",stdin);
// freopen("out.txt","w",stdout);
for (n=0; n<=10; n++)
for (m=0; m<=10; m++)
{
if (m==0) cout<<endl;
if (m>n || n==0)
{
// cout<<0<<endl;
cout<<0<<",";
continue;
}
else if (m==0)
{
// cout<<1<<endl;
cout<<1<<",";
continue;
}
ct[0]=1;
ct[1]=n+1;
ct[2]=(n<<1)+1;
ct[3]=(n<<2);
dlx.init(6*n-2);
for (int i=0; i<n; i++)
for (int j=0; j<n; j++)
{
dlx.addrow(i,j);
}
int k=0;
ans[0].x=ans[0].y=0;
sp=0;
dlx.dfs(0);
// cout<<sp<<endl;
cout<<sp<<",";
}
return 0;
}
表:
#include <iostream>
int ans[11][11]=
{
0,0,0,0,0,0,0,0,0,0,0,
1,1,0,0,0,0,0,0,0,0,0,
1,4,0,0,0,0,0,0,0,0,0,
1,9,8,0,0,0,0,0,0,0,0,
1,16,44,24,2,0,0,0,0,0,0,
1,25,140,204,82,10,0,0,0,0,0,
1,36,340,1024,982,248,4,0,0,0,0,
1,49,700,3628,7002,4618,832,40,0,0,0,
1,64,1288,10320,34568,46736,22708,3192,92,0,0,
1,81,2184,25096,131248,310496,312956,119180,13848,352,0,
1,100,3480,54400,412596,1535440,2716096,2119176,636524,56832,724
};
using namespace std;
int main()
{
int a,b;
while(cin>>a>>b)
{
if (b>a)
{
cout<<0<<endl;
}
else
cout<<ans[a][b]<<endl;
}
return 0;
}