[USACO] The Clocks

最近要面试,于是在USACO上做题来回复一些算法和数据结构方面的能力。今天做到了Clocks这题。简单分析了一下,觉得是一个广度优先搜索。跑过样例数据之后提交测试,发现第三组数据跑挂了。我当时估算了一下算法,所有的状态数大概是4^9,如果单位操作的时间复杂度不是很高的话,应该不会超时。于是觉得是自己写错了一些地方,导致死循环之类的。反复检查了一下代码,发现不是这样的。于是开始写优化……

     首先想到就是拿空间换时间。因为我们知道广搜的大概框架如下:

private void search()
{
    int head = 0;
    
    while (head < this.statusesSize)
    {            
        if (this.statuses[head].isFinished)
        {
            this.finishedStatus = this.statuses[head];
            
            return
        }
        
        this.extractNode(this.statuses[head]);
        
        head ++;
    }
}

      而扩展节点的时候,我们根据规则生成了新的节点之后,就要判重,如果没有重复,就加入队列。我一开始写的是和每一个已有的节点对比,为了提高时间效率,我给状态做了一个hash。因为每个状态需要区分的就是9个钟的状态,而每个钟的状态可以看成一个4进制数。这个地方就直接把状态算成一个9位的4进制数就好了。Hash值就是当前的9位4进制数转换到十进制的值。然后用一个大的boolean数组来标记是否出现过。

     这个优化效果不错。但是第五组还是第六组数据过不去。然后我看了一下题目,要求最优解。很容易可以证明,在操作数不变的情况下,以非降序排列是最小的解决方案。所以我规定了,广搜的时候,只有把前面的扩展方法扩展完,才能扩展后面的方法。来保证扩展顺序的不降序。这个优化使得效果提升了一些。但是还是不够。

     好吧,然后我又做了一些常数优化,发现还是不行。只好去观察扩展规则。发现在规则4之后,第一个时钟不会被改变。我把这个作为剪枝条件写进去了……然后就OK。好蛋疼……

posted on 2013-03-05 18:00  hibix  阅读(496)  评论(0编辑  收藏  举报

导航