Description
Input
Output
Sample Input
4
2 3
111
101
4 2
01
01
11
01
2 1
1
1
3 2
10
10
11
4
1 4
1111
1 4
1111
1 4
1111
1 4
1111
4
1 4
1111
1 4
1111
1 4
1111
2 3
111
001
Sample Output
Yes, only one!
1112
1412
3422
3442
Yes, many!
No solution
Data Constraint
30%的数据,N<5
100%的数据,N<=16
分析
由于每一个piece都不能旋转和反转,所以每一个r ∗c的piece,他只能 有(4−r+1)∗(4−c+1)种摆放的位置。枚举摆放的位置,构建 dancing-link 模型,要求4∗4个方格都被覆盖,并且每一个piece都要用到,所以总共需 要覆盖4∗4 + n列。每一种摆放位置覆盖了他所有的’1’的位置的列以及这 个piece的列。最后搜索到4*4+n列都被覆盖时,就是一个可行解。类似于 数独。
代码
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
const int INF=0x1f1f1f1f;
#define N 4
int res[N][N];
int cnt[100];
int sz[100];
int C,R;
struct Node
{
Node *u,*d,*l,*r;
int n;
}*nd,nodes[50000],*row[1000],*col[100],*stack[5000];
int top;
Node* newNode(int p)
{
nd->u=nd->d=nd->r=nd->l=nd;
nd->n=p;
if(p>=0)cnt[p]++;
return nd++;
}
void init(int c)
{
top=0;
C=c;
R=0;
nd=nodes;
memset(cnt,0,sizeof(cnt));
for(int i=0;i<c;i++)
{
col[i]=newNode(-1);
}
}
void link(Node *a,Node *b,Node *c)
{
a->r=b->r;
a->l=b;
b->r->l=a;
b->r=a;
a->d=c->d;
a->u=c;
c->d->u=a;
c->d=a;
}
void addRow()
{
row[R]=newNode(-1);
R++;
}
void readd(Node *a)
{
a->l->r=a;
a->r->l=a;
a->u->d=a;
a->d->u=a;
cnt[a->n]++;
}
void del(Node *a)
{
a->l->r=a->r;
a->r->l=a->l;
a->u->d=a->d;
a->d->u=a->u;
cnt[a->n]--;
stack[top++]=a;
}
bool delRow(Node *a)
{
while(true)
{
Node *tt=a->r;
if(tt->n==-1)tt=tt->r;
del(tt);
if(cnt[tt->n]==0)return true;
if(tt==a)return false;
}
}
bool delCol(Node *a)
{
while(true)
{
Node *tt=a->d;
if(tt->n==-1)tt=tt->d;
if(tt==a)
{
del(tt);
return false;
}
if(delRow(tt))return true;
}
}
int CC;
int ans[N][N];
void dfs(int step)
{
if(CC>1)return;
if(step==C)
{
memcpy(ans,res,sizeof(res));
CC++;
return;
}
int m=INF;
int k;
for(int i=0;i<C;i++)
{
if(cnt[i]>0&&cnt[i]<m)
{
m=cnt[i];
k=i;
}
}
if(m==INF)
return;
for(Node *arr=col[k]->d;arr!=col[k];arr=arr->d)
{
int tmp=top;
int num;
vector<int>pos;
while(true)
{
Node *tt=arr->r;
if(tt->n==-1)tt=tt->r;
if(tt->n<N*N)pos.push_back(tt->n);
else num=tt->n-N*N+1;
if(delCol(tt))break;
if(tt==arr)
{
for(int ii=0;ii<pos.size();ii++)
res[pos[ii]/N][pos[ii]%N]=num;
dfs(step+sz[num]);
break;
}
}
while(top>tmp)
{
top--;
readd(stack[top]);
}
}
}
char ch[N][N];
int Hash(int x,int y)
{
return x*N+y;
}
int main()
{
freopen("puzzle.in", "r", stdin);
freopen("puzzle.out", "w", stdout);
int n;
while(scanf("%d",&n) != EOF)
{
init(16+n);
for(int id=1;id<=n;id++)
{
int a,b;
scanf("%d%d",&a,&b);
for(int i=0;i<a;i++)
scanf("%s",ch[i]);
for(int sx=0;sx+a<=N;sx++)
for(int sy=0;sy+b<=N;sy++)
{
addRow();
sz[id]=1;
for(int i=0;i<a;i++)
for(int j=0;j<b;j++)
{
if(ch[i][j]=='1')
{
link(newNode(Hash(i+sx,j+sy)),row[R-1],col[Hash(i+sx,j+sy)]);
sz[id]++;
}
}
link(newNode(N*N-1+id),row[R-1],col[N*N-1+id]);
}
}
CC=0;
dfs(0);
if(CC==0)
printf("No solution\n");
else if(CC>1)
{
printf("Yes, many!\n");
}
else
{
printf("Yes, only one!\n");
for(int i=0;i<N;i++)
{
for(int j=0;j<N;j++)
printf("%d",ans[i][j]);
printf("\n");
}
}
}
}