这两天得题,要不超时的超时没有思路得没有思路,刷题水逆的几天干。加油干吧,总归是要努力的,不仅是为了自己,也要为了未来。谁让我们是:
鲜衣怒马少年时,不负韶华行且知
本文由爱吃苹果的清梦,友情赞助
题目描述
有假币
题目解析
首先表明,我刚看到题的时候是蒙掉的,这难道就是简单的二分么,直接求logn就行了嘛??当然,在我试了之后发现阿哲,我的出来的结果和人家的输出好像有亿点点差别:
如果按照二分的思路进行查找的话,我们要把它们不断的区分成两部分进行称量:
我们可以发现跟样例刚好符合,这时候,我们正满心欢喜的是在oj平台进行测试的时候,看到卡样例的时候,心情是难受的。被样例打了一巴掌。
我们仔细观看,发现当是九枚硬币的时候出现了bug,我们好像是多称了,那该怎么处理呢,看来二分是行不通的了,那么我们返回去思考难道3对应的一次并不是用二分算出来的??我们看到这个,简单的操作后不难发现,他其实是分成了三份,只要把其中两份称完,就能判断第三份有没有假的。
所以,我们可以类比到其他的组合,我们就可以发现我们之前样例的错误就节约了,所以,我们就得以总结出来以下的规律:
- 我们在区分假币的时候要将整体的硬币区分成三组,要保证其中的两组不能,小于第三组就能测出,因为我们要保证我们在决策的时候,舍去最多的硬币。
- 在测定的时候,我们要有一定的预见性,就是类似于三个硬币时候,我们要尽量避免重复计算。
所以,我们对于九个的我们加以展示一下,看我们的逻辑推理链路有没有错误
经过不断的排除之后,我们总能回归到10之下的,所以我们可以建立一个三个的映射或者是10以内的,映射图。
那我们的总体思路,就是对数字进行处理,当处理到三的时候,直接进行返回就行,类似于递归之类的。
可以看到的是我们分的时候,是基于我们已知的问题最小单元进行处理的,所以,我们可以将三当成递归条件,但是还有一种情况,所给的样例不总是三的倍数,当不是三的倍数的时候我们应该怎么进行处理呢。
应该采取,向上取整的算法进行处理即可
代码实现
#include<iostream>
#include<algorithm>
using namespace std;
int main()
{
int n = 0;
while(cin >> n && n)
{
int cnt = 0;
while (n)
{
int tem = 0;
if(n == 1) break;
if (n == 2 || n == 3)
{
cnt++;
break;
}
if (n % 3)
{
n /= 3;
n++;
}
else
{
n /= 3;
}
cnt++;
}
cout << cnt << endl;
}
return 0;
}
后记
对于这个智力题的算法逻辑要注意加强,因为一些想法太理所当然了,既然已经有了,问题的基本元,我们就要想办法将问题回归到我们的问题基本当中去。要有递归思想,不能只是为了复现输入输出进行使劲。
本人实力有限,如有谬误,请多见谅。