EOJ 1627. Binary Code

/* 写在前头,是普通SE学生,记性不太好,写过的题容易忘,记录一下*/

题面:

单点时限: 2.0 sec
内存限制: 256 MB

考虑一个 N 位的二进制串 b1…bN,其对应的二进制矩阵为:
在这里插入图片描述
然后将这个矩阵的行按照字典顺序排序,‘0’ 在 ‘1’ 之前。

你的任务是编写一个程序,给定排序后的矩阵的最后一列,求出已排序的矩阵的第一行。

例如:考虑二进制串(00110),排序后的矩阵为:

0 0 0 1 1

0 0 1 1 0

0 1 1 0 0

1 0 0 0 1

1 1 0 0 0

则该矩阵的最后一列为(1 0 0 1 0)。给出了这一列,你的程序应该确定第一行为(0 0 0 1 1)。

输入格式
输入第一行包含一个整数 N(0<=20000),表示二进制串的位数。第二行包含 N 个整数,表示已排序的矩阵的最后一列(从上到下)。

输出格式
输出文件仅一行,包含 N 个整数,从左到右依次表示已排序的矩阵的第一行;若无解,则输出-1。

样例

input
5
1 0 0 1 0
output
0 0 0 1 1

思路
首先我们可以明确一点,在这个矩阵里每一列的0和1的个数相同。
给出的数据是排序好的矩阵的最后一列,所以我们可以得出将所有行数据右移一位之后各行数据所对应的新位置。

以题目给的样例来说,每一列共有3个0和2个1,所以前三行的第一位必然是0,后两行第一位是1,右移后的新顺序即为0、1的顺序。

第一行左移后就会变成第二行(第1个0出现的行),以此类推,第二行变第三行,第三行变第五行,第四行变第一行,第五行变第四行,因为这是左移后得到的顺序,所以原顺序的最后一个元素即为新顺序的倒数第二个元素。

画个简图:
在这里插入图片描述
所以,我们只需要用两个数组储存原顺序和新顺序,然后一步步往前推,最后输出第一行即可。

ac代码

#include <iostream>
using namespace std;
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
#define maxn 20001
int main(int argc, char** argv) 
{
	int zero,one,total,n,cnt=0;
	char input[maxn],*p;
	int temp[maxn],next[maxn];
	cin >> n;
	cin.get();
	p=input;
	zero=one=total=0;
	char ch;
	while(cin.get(ch))
	{
		if(ch=='0'||ch=='1')
		{
			*p=ch;
			p++;
		}
	}
	p=input;
	while(*p)
	{
		if(*p=='0')
		{
			next[zero++]=total;
			cnt++;
		}
		else if(*p=='1')
			temp[one++]=total;
		total++;
		p++;
	}
	int i,j;
	for(i=0;i<one;i++)
	{
		next[zero++]=temp[i];
	}
	char output[maxn];
	for(i=j=0;i<total;i++)
	{
		output[i]=input[next[j]];
		j=next[j];
		if(output[i]=='0')
			cnt--;
	}
	if(cnt)
	{
		cout << -1;
		return 0;
	}
	for(i=0;i<total;i++)
	{
		cout << output[i] << " ";
	}
	
	return 0;
}
  • 5
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值