二进制矩阵 POJ1147

来源:互联网 发布:netbeans for php使用 编辑:程序博客网 时间:2024/06/02 04:58

Binary codes
Time Limit: 1000MS Memory Limit: 65536KTotal Submissions: 4925 Accepted: 1869

Description

Consider a binary string (b1…bN) with N binary digits. Given such a string, the matrix of Figure 1 is formed from the rotated versions of the string.

b1b2…bN−1bNb2b3…bNb1…bN−1bN…bN−3bN−2bNb1…bN−2bN−1

Figure 1. The rotated matrix

Then rows of the matrix are sorted in alphabetical order, where ‘0’ is before ‘1’. You are to write a program which, given the last column of the sorted matrix, finds the first row of the sorted matrix.

As an example, consider the string (00110). The sorted matrix is

0001100110011001000111000

and the corresponding last column is (1 0 0 1 0). Given this last column your program should determine the first row, which is (0 0 0 1 1).

Input

The first line contains one integer N ≤ 3000, the number of binary digits in the binary string. The second line contains N integers, the binary digits in the last column from top to bottom.

Output

The first line contains N integers: the binary digits in the first row from left to right.

Sample Input

51 0 0 1 0

Sample Output

0 0 0 1 1

题意:

N位的二进制串连续N次循环移位,得到N个二进制串。对其按照字典序排列,得到一个N*N的矩阵。告诉矩阵最后一列,求矩阵第一行。

分析:

明白题意后,可能会怀疑只有最后一列是否能得出唯一的第一行内容,当然答案是肯定的。但最初我想可以用穷举法,利用给出的一列,得到所有可能排列。然后对每种排列生成矩阵,然后对比最后一列与给定串一致的便得到了正确的矩阵,输出第一行即可。但复杂度相当大,在网上搜索了一下看到一种线性算法。我开始观察矩阵的数值规律,并以串1 0 1 0 0为例说明。

循环移位、排序后的矩阵如下:

0 0 1 0 1

0 1 0 0 1

0 1 0 1 0

1 0 0 1 0

1 0 1 0 0

    首先知道最后一列数据(用暗红色标出)last[]={1,1,0,0,0},根据0、1的个数和从小到大的排列顺序,可以得出第一列的数据(浅蓝色标出),first[]={0,0,0,1,1}。对于前三行首位都为0的串,如果都循环左移一位,那得到的串依然是从小到大的顺序排列,而且每个串都对应着矩阵中的一个串。所以对于first列第二个出现‘0’的串01001,对应的肯定是在last列中第二个出现‘0’的10010串。对于首位为‘1’的串同样如此。可以得到如下所示的next[]数组。


程序源代码如下:

#include <iostream>using namespace std;int main(){int n;cin>>n;bool *last=(bool *)malloc(n);bool *first=(bool *)malloc(n);int *next=(int *)malloc(sizeof(int)*n);int i,oneNum;oneNum=0;for(i=0;i<n;i++){cin>>last[i];if(last[i])oneNum++;}memset(first,0,n-oneNum);         //统计1的个数 对first数组赋初值memset(first+n-oneNum,1,oneNum);int zeroPos,onePos;zeroPos=onePos=0;for(i=0;i<n;i++){if(first[i]==true){while(last[onePos]!=true)onePos++;next[i]=onePos;onePos++;}else{while(last[zeroPos]!=false)zeroPos++;next[i]=zeroPos;zeroPos++;}}int order=0;for(i=0;i<n-1;i++){cout<<first[order]<<" ";order=next[order];}cout<<first[order]<<endl;return 0;}

输入case:

5

1 1 0 0 0

输出结果:

0 0 1 0 1

原创粉丝点击