蓝桥二进制王国C语言实现

文章讲述了在一个二进制国家中,国王需要根据字典序最小的原则对N户家庭的二进制字符串进行排序,以形成最优排队序列。作者提供了内存管理和最小字典序排序的解决方案,用于处理大量二进制字符串问题。
摘要由CSDN通过智能技术生成

原题

《二进制王国》

问题描述

二进制王国是一个非常特殊的国家,因为该国家的居民仅由0和1组成。

在这个国家中,每个家庭都可以用一个由0和1组成的字符串S来表示,例如101、000、111等。

现在,国王选了出 N户家庭参加邻国的庆典。为了符合王国的审美标准,我们需要选择一种排队顺序,使得最终形成的队伍在字典序上是最小的。

国王将这个任务交给了你,请你解决这个问题。

输入格式

第一行包含一个整数N(1≤N≤2×10^5),代表二进制家庭数量。

接下来输入N行,第i行输入一个二进制字符串Si表示第i户家庭。

数据范围保证:∑|Si|≤2×10^5,其中|Si|表示第i个字符串的长度。(即总数据长度小于2e5)

输出格式

输出一行一个字符串,表示字典序最小的排队情况。

输入样例

3
111
000
101

输出样例

000101111

网址:https://www.lanqiao.cn/problems/17035/learning/

思路简述

1、存储

由题,字符串总长度是2e5。若假设每个字符串的长度不超过2500,最多一共1000个字符字符串,则需要分配2.5e6字节的内存,大约是2.5MB。

而一次性性分配1e6字节的数据是可以接受的,大约是1MB,即char data[(int)1e6] 或 int data[int(1e5)]。所以char data[1000][2500]会报错(图一)。

故我们使用一个长度为2 * 2e5字节的字符串灵活储存所有的字符串数据,和一个长度为2e5的字符串指针数组来储存每个字符串数据的首地址。2 * 2e5是为了存储2e5个单字字符串和它们的结束符'\0'。

小结1:

最大分配内存:

int data[(int)1e5]; char data[(int)1e6];

2、最小字典序

首先什么是字典序?简单的说:"1", "10", "11"。第一位都是'1',往后比。在前段字符相同的情况下,长度短的在前,故"1"在最前面。接着往后比,据ASCII,'0' = 48,'1' = 49,48 < 49,所以"10"在"11"前。

所以我们只用将各个字符串数据以字典序排列就行了?

NO!

题目要求我们使得拼接后的字典序最小。

即:下列测试样例输出的结果应为10010,而非10100,即使"10"的字典序在"100"之前。

测试样例

2
10 100

测试结果

10010

 

因为"10010"的字典序在"10100"之前。

如何实现呢?

我们只需保证任意两个字符串数据拼接后的字典序最小即可。

即:比较str1+str2和str2+str1,而非str1和str2。

小结2:

最小字典序        ASCII    '1', '10', '11'     拼接最小字典序         "10", "100", "10010"         比较str1+str2和str2+str1


源码

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

const int MaxLen = 2E5;
const int MaxSing = 2500; // I guess

int cmp();

int main() {
	int N; //  N strings
	char str[2 * MaxLen]; //  store all datas
	char * pos[MaxLen]; //  the position of strs
	int p;
	
	//  ReadStr
	scanf("%d", &N);
	p = 0;
	for (int i = 0; i < N; ++i) {
		scanf("%s", &str[p]);
		pos[i] = &str[p];
		do { ++p; } while (str[p - 1] != '\0');
	}
	
	
	//  qsort
	qsort(pos, N, sizeof(pos[0]), cmp);
	
	//  output;
	for (int i = 0; i < N; ++i) {
		printf("%s", pos[i]);
	}
	return 0;
}

int cmp(const void * pos1,const void * pos2) {
	const char * s1 = *((const char **) pos1);
	const char * s2 = *((const char **) pos2);
	char _s1[MaxSing * 2], _s2[MaxSing * 2];
	strcpy(_s1, s1);
	strcat(_s1, s2);	
	strcpy(_s2, s2);		
	strcat(_s2, s1);
	
	return strcmp(_s1, _s2);	
}

  • 7
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值