57 数字游戏
Posted manok
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了57 数字游戏相关的知识,希望对你有一定的参考价值。
57 数字游戏
作者:
问题描述 :
现在,有许多给小孩子玩的数字游戏,这些游戏玩起来简单,但要创造一个就不是那么容易的了。 在这,我们将介绍一种有趣的游戏。
你将会得到N个正整数,你可以将一个整数接在另一个整数之后以制造一个更大的整数。 例如,这有4个数字123, 124, 56, 90,他们可以制造下列整数─ 1231245690, 1241235690, 5612312490, 9012312456, 9056124123....等,总共可以组合出24(4!)种数字。 但是,9056124123是最大的那一个。
你可能会想这是个简单的事情,但对刚有数字概念小孩来说,这会是个简单的任务吗?
输入说明 :
输入含有多组测试数据。
每组测试资料两行,第一行为一个正整数N(N<= 50),第二行将有N 个正整数。
当N=0代表输入结束。
输出说明 :
对每一组测试数据,输出一行,输出利用这N个整数可结合成的最大整数。
输入范例 :
5
123 124 56 90 9
1
1
5
991 9909 99 990 989
2
191 1919
0
输出范例 :
99056124123
1
999919909990989
1919191
总结,这道题目有着深刻的教训!!!
1、关于C语言的字符串操作及内存分析理解不到位,具体表现在 字符串数组和字符串指针区别遗忘。详解C语言字符串指针
2、对于全排列问题的深度优先搜索不是很理解,也就是说不借助于工具书写不出来。(递归)
3、DFS的剪枝经验不足,当数据量增大时,超时!
4、轻视了题目的数据规模,这个数据规模值得不仅仅是数据量,也保持了数据的排列方式。例如两个极端的测试案例(测试要有极端案例)
测试样例一:
测试样例一有什么意义呢?
第一:可以检验程序在极端情况下是否正常输出
第二:可以测试程序在极端情况下的耗时
通过这个测试样例,我很明显看到了倒序的数据输入耗时明显少于正序,而第一种输入甚至死循环也没出结果。这种情况其实是算法有问题。
毕竟50!次运算量很大。
那么,我就想到了一种有效的剪枝方法,即在全排列之前,可以先按照某种模糊的要求将记录数据的内容排序。使得全排列过程中可以提前
找打较大,甚至是最大的值。这个有什么用呢?单纯这种剪枝方法没有效果,要结合第二种剪枝,即在进入下一层DFS之前,提前将下一层的
结果和当前记录最大值进行比较,可以预判下一层的DFS是否已意义。如果没必要进行下一层,直接返回。大大减小计算量。详见代码。
测试样例二:(这个是点击官方案例才拿到的,没想到官方给的整数长度超过了30,不过这也合理)
这个测试样例给予我深刻的印象,我会记你一辈子的。
简答总结一下思路和遇到的问题
今天早上的思路是就是通过字符串数组录入字符串,然后将字符串数组DFS全排列,全排列的过程通过索引生成完整的字符串(整数),
刷新最大值(通过strcmp)。这个思路是正确的。但是栽了不少坑。
1、刚开始没有用strcpy赋值字符串,使用的是max_str = str;导致输出的最大值一直是最后一个数据。
这个牵涉到字符串指针的理解
如果使用max_str = str这个的话,对字符数组str[]赋值,那么max_str肯定会跟着改变。
2、DFS剪枝,刚开始的剪枝单纯采用if(strncmp(temp,max_str,strlen(temp))>=0),即避免
本次91开始递归,记录最大值是92……。很明显无需递归下一层。似乎超时的样例少了一个。
3、下午索性自己造数据,造极端数据看看超时有多严重。
for循环产生
超时挺严重的,程序仿佛死循环,50!惹不起。
思考为啥有这么大的计算量,一看就很明显,前面的计算都没有意义,应当尝试将数据逆序下。
如下:
不到半秒就出结果了。!
这个给予我很大启示,在进行DFS之前,应当尽量先将记录数排序下,排序的目的使得DFS可以尽早找到较大值甚至最大值(减少计算量)
这个排序的方法在我脑海中闪现了一下。
如果数据是1 2 3
那么应当将记录数组该位3 2 1
如果数据是333 222 111 9
那么记录数组应当是9 333 222 111
详细说来
/**
为了减少计算量,提前将数据进行模糊排序
这个模糊排序指的是
比如
9 98如何定义大小呢?
我们规定9>98
因为如果数据集合是9 9 98的话
按照以上定义,我们可以比较快的DFS到9998
也就是尽可能让组成大的数据
但是不能依据这个的单纯的排序,这只是一个模糊的排序
如按照定义:19>192
如果单纯这种排序出结果,那么结果是19192
其实正确答案是 19219,
所以必须DFS比较。
以上的定义大小只是模糊的将“大的”数据放在记录数组的前面,
防止极端数据造成的无意义的DFS(计算量超大,参照1到50的正序数据)
**/
这种排序规则是这样的
1 int myStrcmp(char str1[],char str2[]){ 2 int i=0; 3 while(str1[i]!=‘