题意理解
给出一段N*L的01矩阵,矩阵的一个值代表一个文章的一个字,整个矩阵就是一段文字,0表示模糊(可能有值,也可能无),1表示有字。已知开头两个00是段落的标记,若文章原段落数是M,求0表示的模糊字最少多少?
问题分析
用贪心算法
过程分两步:第一步提取文章最多段落信息(开头是两个或两个以上0的情况),信息包括段落数countM,段落内0个数,段落尾0个数。第二步正式用贪心,要求最终在M个段落下0包含字最少,那就要求合并countM个段落数为M个段落,段落内的0肯定是包含字的,必须算在内,段落尾的0包不包含看该段落有没有被合并,合并了就是包含字的,没合并就不包含字。还有一部分0是段落开头,如果段落没被合并就不包含字,如果段落合并就包含字,长度固定为2。以上三种情况综合起来,合不合并一段关键看段落尾空白多少,要保证最终包含字的0最少,那么合并的段落尾空白越短越好,可以对段落尾0数从小到大排序,需要合并几段就从小到大取几个,再加上段落开头固定的2。
此外,题意隐含一个信息,文章默认有一个段落,最后一段必须独立,不管段落尾空白数量,因为合并不了。与上面的分析结合起来,就是排序尾0数时,不考虑最后一段!
其他
用时耗费点
刷题判断逻辑:系统要求循环输入-输出过程来判断;系统支持的循环过程必须是活循环(可断),死循环报超时!
while(1)
{cin>> N...}
以上方式必超时。
while(cin>>N...)
{}
以上方式可行。
效率分析:我的算法时间是1185ms,参考代码时间是296ms!这就是差距。思路上差异如下
没想到的
没想到最后一段尾0必须保留,
对段落信息数据结构的考虑,想的是段内0,段尾0,段头默认2,从后面用的情况来看,只用段内0,段尾0+端头2合二为一。思路里段落序号,段内0,段落尾0三者必须一致,不可单独排序,实际上根据要求,完全可以先累计段内0,排序段落尾0+端头2,取其前几个相加即可。
想的不好的
抽取段落信息,我的思路是
循环读取每一行:
判断开头是不是两个0,如果是,
判断上一行尾是不是0;如果是
判断行号是不是大于0,如果是
数上一行尾0数,保存
否
不做操作
否
数当前行0数(包含头两位0),保存
否
数当前行0数(包含全部0),保存
问题是尾0数了两遍,重复。参考代码思路是判断下一行是否是双0,如果是,当前段落计算尾0,计算当前行0计入当前段落;...这样就不用重复统计。
贪心算法实现,我的思路是
从尾0列表中(除去最后一个),每次选一个最大的尾0纪录作为保留段落,然后置为-1,直到选出M个段落。
参考代码思路,直接对尾0列表排序,对所有段内0累计,加上尾0排序后的从小到大的前countM-M个数即可。
总结就是,自己的思路停留在贪心的方法上,缺少将贪心集合到题目上的运用能力。删改增可以在灵活一点。下一步眼界看到题目本身的特点,而不是局限方法上。方向上,不再将数量作为最重要的方面,而是一题一题刷透,学到知识,拔掉思维里僵化的刺,脑子能学的活一点再活一点,一点一点流动起来。
代码链接:
自己代码:https://github.com/xierensong/learngit/blob/master/hdu/h1735.cpp
参考代码:https://blog.csdn.net/u013615904/article/details/77620103