应该直接爆搜就可以了。我状压了一下每个位置目前是否被占据,跑得快了一些。不过这样输出路径时有点麻烦x
注意输出的,后面有空格。。。
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
#define N 20
inline int read(){
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
return x*f;
}
int n,r[N],c[N],mp[N],id[5][5],bin[20],ans,a[N];
char s[N],res[5][5],f[N];
inline bool cmp(int a,int b){return mp[a]>mp[b];}
void dfs(int cntt,int S){
if(cntt>n){ans++;return;}int cnt=a[cntt];
for(int i=0;i<=4-c[cnt];++i)
for(int j=0;j<=4-r[cnt];++j){
int ss=(mp[cnt]<<i+4*j)&(bin[16]-1);
if(ss&S) continue;dfs(cntt+1,S|ss);
if(!f[cnt]&&ans>=1){
f[cnt]=1;
for(int x=0;x<r[cnt];++x)
for(int y=0;y<c[cnt];++y)
if(mp[cnt]&bin[id[x][y]])
res[x+j][y+i]=cnt+'0';
}if(ans==2) return;
}
}
int main(){
int num=-1;bin[0]=1;
for(int i=1;i<=16;++i) bin[i]=bin[i-1]<<1;
for(int i=0;i<4;++i)
for(int j=0;j<4;++j) id[i][j]=++num;
while(~scanf("%d",&n)){
int tot=0;bool flag=1;ans=0;memset(f,0,sizeof(f));
for(int i=1;i<=n;++i){
r[i]=read();c[i]=read();if(r[i]>4||c[i]>4) flag=0;mp[i]=0;
for(int j=0;j<r[i];++j){
scanf("%s",s);if(!flag) continue;
for(int k=0;k<c[i];++k)
if(s[k]=='1') ++tot,mp[i]|=bin[id[j][k]];
}
}if(tot!=16||!flag){puts("No solution");continue;}
for(int i=1;i<=n;++i) a[i]=i;sort(a+1,a+n+1,cmp);
dfs(1,0);if(!ans){puts("No solution");continue;}
if(ans==2){puts("Yes, many!");continue;}puts("Yes, only one!");
for(int i=0;i<4;++i) puts(res[i]);
}return 0;
}