T1:
我们能够证明(显然)这样的一个网络能输出任何[0,2^n-1]的排列(可以用归纳法证明),于是-1是不存在的了。
考虑每个节点只有两种状态,能否2-sat做呢?似乎有一些节点的状态是存在依赖关系的,然而并不会建图。
(于是我就写了20分暴力,先枚举那些节点激活然后进行大模拟)
正解是考虑这个网络的形态,观察可得一个节点输出的两个信号会被分配到左右的两个子网络中。
如果我们想构造出解的话,需要让第一次每个节点的两个信号进入两个不同的子网络,最后一层每个节点的两个信号从两个不同的子网络中得来。这个就是依赖关系了。
等等,这个似乎不需要2-sat,因为要字典序最小,我们能钦定第一行第一个节点状态为0,然后通过数值关系推出每个数字必须在哪个子网络中,这样与1号节点存在依赖关系的节点的状态也就都确定了。
然后继续扫描第一行,如果存在某个节点的状态没有被确定,那么让他为0与前面最优化的答案一定不冲突,我们就让他为0,然后继续递推就好了。
然后完成某一级的答案求解后,递归求出两个子网络的状态即可。
复杂度O(n*2^n)。
20分暴力代码:
1 #include<cstdio> 2 #include<algorithm> 3 const int maxn=11; 4 const int inf=0x3f3f3f3f; 5 6 bool sta[maxn][maxn]; 7 int in[maxn][maxn],tar[maxn],Log[maxn]; 8 9 inline int shl(int x,int l) { 10 int ret = 0; 11 for(int i=0;i<l;i++) if( x & ( 1 << i ) ) ret |= 1 << ( ( i - 1 + l ) % l ); 12 return ret; 13 } 14 inline int shr(int x,int l) { 15 int ret = 0; 16 for(int i=0;i<l;i++) if( x & ( 1 << i ) ) ret |= 1 << ( ( i + 1 ) % l ); 17 return ret; 18 } 19 20 inline void solve(int x,int y,int z,int inlev,int outlev,int n) { // doubled data level . 21 if( n == 1 ) return; 22 for(int i=0;i<n>>1;i++) { // cross node from inlev to inlev + 1 . 23 int l = y + i * 2 , r = y + i * 2 + 1; 24 in[inlev+1][l] = in[inlev][l] , in[inlev+1][r] = in[inlev][r]; 25 if( sta[x][(y>>1)+i] ) std::swap(in[inlev+1][l],in[inlev+1][r]); 26 } 27 if( n != 2 ) { 28 for(int i=0;i<n>>1;i++) { // cross line from inlev + 1 to inlev + 2 . 29 int ix = y + i * 2 , iy = y + i * 2 + 1 , ox = y + shl(i*2,Log[n]) , oy = y + shl(i*2+1,Log[n]); 30 in[inlev+2][ox] = in[inlev+1][ix] , in[inlev+2][oy] = in[inlev+1][iy]; 31 } 32 solve(x+1,y,z-1,inlev+2,outlev-2,n>>1) , solve(x+1,y+(n>>1),z-1,inlev+2,outlev-2,n>>1); 33 for(int i=0;i<n>>1;i++) { // cross line from outlev - 1 to outlev . 34 int ix = y + i * 2 , iy = y + i * 2 + 1 , ox = y + shr(i*2,Log[n]) , oy = y + shr(i*2+1,Log[n]); 35 in[outlev][ox] = in[outlev-1][ix] , in[outlev][oy] = in[outlev-1][iy]; 36 } 37 } 38 for(int i=0;i<n>>1;i++) { // cross node from outlev to outlev + 1. 39 int l = y + i * 2 , r = y + i * 2 + 1; 40 in[outlev+1][l] = in[outlev][l] , in[outlev+1][r] = in[outlev][r]; 41 if( sta[z][(y>>1)+i] ) std::swap(in[outlev+1][l],in[outlev+1][r]); 42 } 43 } 44 45 inline bool dif(int n,int n_lev) { 46 for(int i=0;i<1<<n;i++) if( in[n_lev][i] != tar[i] ) return 1; 47 return 0; 48 } 49 inline void unzipsta(int ss,int x,int y) { 50 for(int i=x-1;~i;i--) for(int j=y-1;~j;j--) sta[i][j] = ss & 1 , ss >>= 1; 51 } 52 53 int main() 54 static int sol,n,full,n_nod,m_nod,n_lev; 55 while( scanf("%d",&n) == 1 && n ) { 56 sol = 0 , n_nod = 2 * n - 1 , m_nod = 1 << ( n - 1 ) , n_lev = 2 * n_nod - 1 , full = 1 << ( n_nod * m_nod ); 57 for(int i=0;i<=n;i++) Log[1<<i] = i; 58 for(int i=0;i<1<<n;i++) scanf("%d",tar+i); 59 for(int i=0;i<full&&!sol;i++) { 60 for(int j=0;j<1<<n;j++) in[0][j] = j; 61 unzipsta(i,n_nod,m_nod) , solve(0,0,n_nod-1,0,n_lev-1,1<<n); 62 if( !dif(n,n_lev) ) sol = 1; 63 } 64 if( !sol ) puts("-1"); 65 else { 66 for(int i=0;i<n_nod;i++) { 67 for(int j=0;j<m_nod;j++) putchar('0'+sta[i][j]); 68 putchar('\n'); 69 } 70 } 71 putchar('\n'); 72 } 73 return 0; 74 }