topcoder SRM 501 div1 level1

Problem Statement

 

Fox Ciel was very bored, so she invented a single player game. The rules of the game are:


You start with 0 points.

You make exactly nA+nB moves.

You have two types of moves available. These are called move A and move B.

Exactly nA times you will make move A. Exactly nB times you will make move B. The moves can be in any order.

The moves affect your score in the following ways:

  • Each time you make move A, you add scoreA to your score.
  • Each time you make move B, you multiply your score by scoreB.

You are given int nA, int nB, int paramA and int paramB. Calculate scoreA and scoreB as follows ("/" denotes exact division, without any rounding):

scoreA = paramA/1000.0
scoreB = paramB/1000.0

Return the maximum possible score after nA+nB moves.

Definition

 
Class:FoxPlayingGame
Method:theMax
Parameters:int, int, int, int
Returns:double
Method signature:double theMax(int nA, int nB, int paramA, int paramB)
(be sure your method is public)
 
 

Notes

-The returned value must have an absolute or relative error less than 1e-9.

Constraints

-nA will be between 0 and 50, inclusive.
-nB will be between 0 and 50, inclusive.
-paramA will be between -10000 and 10000, inclusive.
-paramB will be between -2000 and 2000, inclusive.

Examples

0) 
 
5
4
3000
2000
Returns: 240.0
scoreA = 3000/1000 = 3
scoreB = 2000/1000 = 2

The optimal order of operations is:
(3 + 3 + 3 + 3 + 3) * 2 * 2 * 2 * 2 = 240
1) 
 
3
3
2000
100
Returns: 6.0
scoreA = 2000/1000 = 2
scoreB = 100/1000 = 0.1

Multiplying the score by scoreB decreases its absolute value, so it's better to do all multiplications before additions. Thus, the optimal order of operations is:
0 * 0.1 * 0.1 * 0.1 + 2 + 2 + 2 = 6
2) 
 
4
3
-2000
2000
Returns: -8.0
Multiplying the score by scoreB increases its absolute value, but given that scoreA is negative, the overall score will be negative as well, so it's better to do multiplications before additions again to keep the absolute value small.
3) 
 
5
5
2000
-2000
Returns: 160.0
Multiplication increases the absolute value of the score, but if you do all 5 multiplications after additions, you'll end up with negative score. Thus, the optimal order of operations is:
(0 * (-2) + 2 + 2 + 2 + 2 + 2) * (-2) * (-2) * (-2) * (-2) = 160
4) 
 
50
50
10000
2000
Returns: 5.62949953421312E17
5) 
 
41
34
9876
-1234
Returns: 515323.9982341775

This problem statement is the exclusive and proprietary property of TopCoder, Inc. Any unauthorized use or reproduction of this information without the prior written consent of TopCoder, Inc. is strictly prohibited. (c)2003, TopCoder, Inc. All rights reserved.     

【题解】

dp,设f[i][j]为用了i次A,j次B后最大得分,g[i][j]为用了i次A,j次B后最小得分。

则很容易dp,详见代码

【代码】

#include <vector>
#include <list>
#include <map>
#include <set>
#include <deque>
#include <stack>
#include <bitset>
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <ctime>

using namespace std;
const double oo=1e10;

double f[60][60],g[60][60];

class FoxPlayingGame
{
public:
	double theMax(int, int, int, int);
};

double FoxPlayingGame::theMax(int na, int nb, int parama, int paramb)
{
    f[0][0]=g[0][0]=0;
    double sa=parama/1000.0;
    double sb=paramb/1000.0;
    int i,j;
    for (i=0;i<=na;i++)
        for (j=0;j<=nb;j++)
        if (i || j)
        {
            f[i][j]=-oo;g[i][j]=oo;
            if (i)
            {
                f[i][j]=max(f[i][j],f[i-1][j]+sa);
                g[i][j]=min(g[i][j],g[i-1][j]+sa);
            }
            if (j)
            {
                if (sb>0) f[i][j]=max(f[i][j],f[i][j-1]*sb);
                else f[i][j]=max(f[i][j],g[i][j-1]*sb);
                if (sb>0) g[i][j]=min(g[i][j],g[i][j-1]*sb);
                else g[i][j]=min(g[i][j],f[i][j-1]*sb);
            }
        }
    return max(f[na][nb],g[na][nb]);
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值