SRM538-div1-2-TurtleSpy

转载 2012年03月28日 22:21:39

题目大意:
     机器人从起始点开始,可以有个四种动作:
  • 前进X距离
  • 后退X距离
  • 向左旋转X度(1到359之间)
  • 向右旋转X度(1到359之间)
     现在给出一组动作的集合,动作的顺序未知,求该组动作按照一定的次序排列后得到的最大移动距离。
     数据规模:X为[1,1000],动作集合大小为[1,50]
     
     
思路:
     求解这道题的关键在于要观察到如下特点:
  • 旋转的动作是可选的,因为可以把这些旋转动作放在最后,那么对最终位置就不会有任何影响。
  • 最优移动策略中,前进的动作应该是连续的,后退的动作也应该是连续的。也就是说最优路径应该如下图所示,其中蓝色是前进的路线,红色是后退的路线。其中theta夹角表示两条路线之间旋转过的角度。


     第二个特点,看起来比较直观。凭直觉的话,不同的前进(或者后退)动作之间如果加入了旋转动作,那么走出来的路线是曲折的路线,距离必然会小于走直线的路线,所以最优路线应该是先往一个方向前进再往一个方向后退。虽然该命题是正确的(因为通过system test了),但是这种分析并不严谨,需要更加严格的证明,目前本人没想出证明方法。
     建立在这两个特点之上,我们所要解决的问题其实就是找到一个合适的theta使得最终距离最大,根据余弦定理:
                         c=sqrt(a^2+b^2-2*a*b*cost(theta))
theta越接近180度,c的值越大。所以我们需要从所有旋转角度的动作中找到一个组合使得theta的值最接近180度。
     由于角度的取值范围只能是[0,359]中的整数,所以可以用dp算法获得所有可能的角度值,然后选取其中最接近180度的。dp过程与背包问题类似,每考虑一个旋转动作记录一次已有的角度值即可。算法复杂度O(360*n),其中n为旋转动作数。

Java代码:

public class TurtleSpy {
    public double maxDistance(String[] commands) {
        long f = 0, b = 0;
        ArrayList<Integer> angle = new ArrayList<Integer>();
        for (int i = 0; i < commands.length; ++i) {
            String[] ss = commands[i].split(" ");
            int x = Integer.parseInt(ss[1]);
            if (ss[0].equals("forward")) {
                f += x;
            } else if (ss[0].equals("backward")) {
                b += x;
            } else if (ss[0].equals("left")) {
                angle.add(-x);
            } else {
                angle.add(x);
            }
        }
        boolean[] dp = new boolean[360];
        dp[0] = true;
        for (int i = 0; i < angle.size(); ++i) {
            boolean[] next = new boolean[360];
            for (int a = 0; a < 360; ++a){
                if (dp[a]) {
                    next[(a + 360 + angle.get(i)) % 360] |= dp[a];
                    next[a] |= dp[a];
                }
            }
            dp = next;
        }
        int theta = 0;
        for (; theta < 180; ++theta) {
            if (dp[180 - theta] || dp[180 + theta]) {
                break;
            }
        }
        return Math.sqrt(Math.abs(f * f + b * b + 2 * f * b * Math.cos(Math.PI * theta / 180)));
    }
}



相关文章推荐

SRM538-div1-3-SkewedPerspective

zz: http://www.strongczq.com/2012/03/srm538-div1-3-skewedperspective.html 题目原文:http://communit...

SRM538-div2-3-SkewedPerspectives

zz: http://www.strongczq.com/2012/03/srm538-div2-3-skewedperspectives.html 题目原文:http://commu...

topcoder SRM div 2 level 1

Problem Statement   Dmitry likes TopCoder Single Round Matches. Once, he registered for an ...

SRM 492 div1 level 2

There is a kingdom with N cities numbered 0 through N-1. Gogo wants to survey several cities in the...

SRM540-div1-2-RandomColoring

zz: http://www.strongczq.com/2012/04/srm540-div1-2-randomcoloring.html 题目原文:http://community.top...

topcoder SRM500 DIV1 level2 500分

Problem Statement   Nick likes to draw fractals. For the special occasion of Single Round M...

SRM534-div1-2-EllysNumbers

zz: http://www.strongczq.com/2012/03/srm534-div1-2-ellysnumbers.html 题目原文:http://community.topc...

topcoder SRM495 div1 level2

Problem Statement   There are N boxes numbered 0 through N-1. Every box except for one conta...

SRM537-div1-2-KingXMagicSpells

zz: http://www.strongczq.com/2012/03/srm537-div1-2-kingxmagicspells.html 题目原文:http://community.t...

TopCoder SRM558 backup 1 DIV 2

Problem Statement   Surrounding Game is a single-player game played on a rectangular grid o...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:SRM538-div1-2-TurtleSpy
举报原因:
原因补充:

(最多只允许输入30个字)