这道题会做了,NOIP就出什么DLX都不怕了,注意:是NOI“P”。
题意:有12个块,可以任意翻转、旋转,即每个块最多有8种表现形式。现在要求你把它们填进图中。
注:每个块只能用一次。
DLX建图:列55+12,行若干。
当然,我是会给你算好的数据的。
#define N 3000/*每个块“8”种形状就会有2730行*/
#define M 70/*55+12这么多列*/
#define NN 16000/*空图最多15084个点*/
前55列表示位置,每个位置上最多只有一个节点,后12列表示每个块的若干种摆放方案中只能选一个。
建图:每行表示一种摆放方案,记录fid表示其块键值,即记录“A~L”,然后枚举它放在哪里,能放进去就对前55列中某些列加节点,然后再把这行与后12列中的对应列加个节点。
因为方块不变,所以我们可以先打表记录方块的形状。
因为基本不会TLE,所以我们没必要打12*8个方块,我们只需要打12个方块的表就好了,表的打法如下。
const int lenx[20]={3,4,4,4,5,5,5,5,5,5,5,5};
const int table[15][10][5]=
{
/*A*/{{0,0},{1,0},{0,1}},
/*B*/{{0,0},{0,1},{0,2},{0,3}},
/*C*/{{0,0},{1,0},{0,1},{0,2}},
/*D*/{{0,0},{1,0},{0,1},{1,1}},
/*E*/{{0,0},{1,0},{2,0},{2,1},{2,2}},
/*F*/{{0,0},{0,1},{1,1},{0,2},{0,3}},
/*G*/{{0,0},{1,0},{0,1},{0,2},{1,2}},
/*H*/{{0,0},{1,0},{0,1},{1,1},{0,2}},
/*I*/{{0,0},{0,1},{0,2},{1,2},{1,3}},
/*J*/{{0,0},{-1,1},{0,1},{1,1},{0,2}},
/*K*/{{0,0},{1,0},{1,1},{2,1},{2,2}},
/*L*/{{0,0},{1,0},{0,1},{0,2},{0,3}}
};
每个table[i][j]表示第i个图形的第j个格子与第0个格子的横纵坐标差值(不是加绝对值的那种差值),
然后用的时候进行枚举
Ⅰ.每个点的{a,b}中a应该加到x还是y上,
Ⅱ.每个点的x值需要加还是减,
Ⅲ.每个点的y值需要加还是减。
实现:
int nx[2],mul[2]={-1,1};
for(shape=0;shape<12;shape++)
{
elist++;
for(tx=0;tx<2;tx++)
for(xm=0;xm<2;xm++)
for(ym=0;ym<2;ym++)
/*样子枚举完毕*/
for(ti[0]=1;ti[0]<=10;ti[0]++)
for(ti[1]=1;ti[1]<=ti[0];ti[1]++)
就是这样简单。
好了,贴完整代码。
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define N 3000/*每个块“8”种形状就会有2730行*/
#define M 70/*55+12这么多列*/
#define NN 16000/*空图最多15084个点*/
#define inf 0x3f3f3f3f
using namespace std;
const int lenx[20]={3,4,4,4,5,5,5,5,5,5,5,5};
const int table[15][10][5]=
{
/*A*/{{0,0},{1,0},{0,1}},
/*B*/{{0,0},{0,1},{0,2},{0,3}},
/*C*/{{0,0},{1,0},{0,1},{0,2}},
/*D*/{{0,0},{1,0},{0,1},{1,1}},
/*E*/{{0,0},{1,0},{2,0},{2,1},{2,2}},
/*F*/{{0,0},{0,1},{1,1},{0,2},{0,3}},
/*G*/{{0,0},{1,0},{0,1},{0,2},{1,2}},
/*H*/{{0,0},{1,0},{0,1},{1,1},{0,2}},
/*I*/{{0,0},{0,1},{0,2},{1,2},{1,3}},
/*J*/{{0,0},{-1,1},{0,1},{1,1},{0,2}},
/*K*/{{0,0},{1,0},{1,1},{2,1},{2,2}},
/*L*/{{0,0},{1,0},{0,1},{0,2},{0,3}}
};
const int crsx[60]=
{
0 ,
1 ,
2 ,2 ,
3 ,3 ,3 ,
4 ,4 ,4 ,4 ,
5 ,5 ,5 ,5 ,5 ,
6 ,6 ,6 ,6 ,6 ,6 ,
7 ,7 ,7 ,7 ,7 ,7 ,7 ,
8 ,8 ,8 ,8 ,8 ,8 ,8 ,8 ,
9 ,9 ,9 ,9 ,9 ,9 ,9 ,9 ,9 ,
10,10,10,10,10,10,10,10,10,10
};
const int crsy[60]=
{
0 ,
1 ,
1 ,2 ,
1 ,2 ,3 ,
1 ,2 ,3 ,4 ,
1 ,2 ,3 ,4 ,5 ,
1 ,2 ,3 ,4 ,5 ,6 ,
1 ,2 ,3 ,4 ,5 ,6 ,7 ,
1 ,2 ,3 ,4 ,5 ,6 ,7 ,8 ,
1 ,2 ,3 ,4 ,5 ,6 ,7 ,8 ,9 ,
1 ,2 ,3 ,4 ,5 ,6 ,7 ,8 ,9 ,10
};
char TS[30][30];
struct DLX
{
int elist,eline;
int stid[30][30];
int eid[M];
int fid[N];
bool visit[30];
int U[NN],D[NN],L[NN],R[NN],C[NN],V[NN];
int H[N],T[M],cnt;
int ans[30][30];
inline void newnode(int x,int y)
{
C[++cnt]=y;V[cnt]=x;T[y]++;
if(!H[x])H[x]=L[cnt]=R[cnt]=cnt;
else L[cnt]=H[x],R[cnt]=R[H[x]];
R[H[x]]=L[R[H[x]]]=cnt,H[x]=cnt;
U[cnt]=U[y],D[cnt]=y;
U[y]=D[U[y]]=cnt;
}
inline void remove(int x)
{
for(int i=D[x];i!=x;i=D[i])
{
for(int j=R[i];j!=i;j=R[j])
{
U[D[j]]=U[j];
D[U[j]]=D[j];
T[C[j]]--;
}
}
L[R[x]]=L[x];
R[L[x]]=R[x];
}
inline void resume(int x)
{
for(int i=U[x];i!=x;i=U[i])
{
for(int j=L[i];j!=i;j=L[j])
{
U[D[j]]=j;
D[U[j]]=j;
T[C[j]]++;
}
}
L[R[x]]=x;
R[L[x]]=x;
}
inline void build()
{
int ti[2],i,j,k;
for(i=1;i<=10;i++)for(j=1;j<=i;j++)if(TS[i][j]!='.')visit[TS[i][j]-'A']=1;
for(i=1;i<=10;i++)for(j=1;j<=i;j++)stid[i][j]=++elist;
cnt=elist+12;
for(i=1;i<=cnt;i++)
{
U[i]=D[i]=i;
L[i]=L[0],R[i]=0;
L[0]=R[L[0]]=i;
}
int tx,xm,ym,shape;
int nx[2],mul[2]={-1,1};
for(shape=0;shape<12;shape++)
{
elist++;
for(tx=0;tx<2;tx++)
for(xm=0;xm<2;xm++)
for(ym=0;ym<2;ym++)
/*样子枚举完毕*/
for(ti[0]=1;ti[0]<=10;ti[0]++)
for(ti[1]=1;ti[1]<=ti[0];ti[1]++)
{
for(k=0;k<lenx[shape];k++)
{
nx[ tx ]=ti[ tx ]+mul[xm]*table[shape][k][0];
nx[tx^1]=ti[tx^1]+mul[ym]*table[shape][k][1];
if(visit[shape]){if(TS[nx[0]][nx[1]]!='A'+shape)break;}
else if(TS[nx[0]][nx[1]]!='.')break;
}
if(k==lenx[shape])
{
fid[++eline]=shape;
for(k=0;k<lenx[shape];k++)
{
nx[ tx ]=ti[ tx ]+mul[xm]*table[shape][k][0];
nx[tx^1]=ti[tx^1]+mul[ym]*table[shape][k][1];
newnode(eline,stid[nx[0]][nx[1]]);
}
newnode(eline,elist);
}
} }
}
inline bool dfs()
{
if(!R[0])return true;
int S=R[0],W=T[S],i,j;
for(i=R[S];i;i=R[i])if(T[i]<W)
{
W=T[i];
S=i;
}
remove(S);
for(i=D[S];i!=S;i=D[i])
{
if(C[i]<=55)ans[crsx[C[i]]][crsy[C[i]]]=fid[V[i]];
for(j=R[i];j!=i;j=R[j])
{
remove(C[j]);
if(C[j]<=55)ans[crsx[C[j]]][crsy[C[j]]]=fid[V[j]];
}
if(dfs())return true;
for(j=L[i];j!=i;j=L[j])resume(C[j]);
}
resume(S);
return false;
}
inline void ret()
{
for(int i=1;i<=10;i++)
{
for(int j=1;j<=i;j++)printf("%c",ans[i][j]+'A');
puts("");
}
}
inline void work()
{
build();
if(dfs())ret();
else puts("No solution");
}
}dlx;
int main()
{
// freopen("test.in","r",stdin);
// freopen("my.out","w",stdout);
for(int i=1;i<=10;i++)scanf("%s",TS[i]+1);
dlx.work();
return 0;
}