TopCoder SRM 602 Div1 第1题

Problem Statement

 

TypoCoder is a programming contest like TopCoder. TypoCoder also has a rating system. There are two types of coders in TypoCoder: brown coders and ciel coders. A brown coder is a coder whose rating is greater than or equal to 2200. A ciel coder is a coder whose rating is less than 2200.

Cat Lower competes in TypoCoder. He is currently a ciel coder. His rating at the end of the current year is X.

Next year there will be some contests. In each of those contests, Cat Lower can either try his best or lose on purpose. For each i, the i-th contest (0-based index) has weight D[i]. If Cat Lower tries his best in the i-th contest, his rating will increase by D[i]. If he decides to lose on purpose instead, his rating will decrease by D[i], but not below zero. Formally, his rating will decrease by min(D[i],his rating before the contest).

Cat Lower loves being a ciel coder. Therefore, he must never be a brown coder twice in a row. That is, whenever Cat Lower becomes a brown coder, he must be ciel again after the next contest (if there are any contests left).

TypoCoder awards "Chameleon coder of the year" to the coder whose color changed the most times during the year.

You are given the vector <int> D and the int X. Return the maximal number of color changes Cat Lower can have next year.

Definition

 

Class:

TypoCoderDiv1

Method:

getmax

Parameters:

vector <int>, int

Returns:

int

Method signature:

int getmax(vector <int> D, int X)

(be sure your method is public)

Limits

 

Time limit (s):

2.000

Memory limit (MB):

256

Constraints

-

D will contain between 1 and 50 elements, inclusive.

-

Each element of D will be between 0 and 1,000,000,000 (10^9), inclusive.

-

X will be between 0 and 2199, inclusive.

Examples

0)

 

 

{100,200,100,1,1}

2000

Returns: 3

When he increase at the second, the third and the last competition and decrease at the first and the fourth competition, he can change the color 3 times and this is the maximal.

1)

 

 

{0,0,0,0,0}

2199

Returns: 0

He cannot be a brown coder in this case.

2)

 

 

{90000,80000,70000,60000,50000,40000,30000,20000,10000}

0

Returns: 1

Note that Cat Lower always has at least one valid strategy: if he decides to lose in all contests, he will remain ciel forever. In this test case, the optimal strategy for him is to lose in the first eight contests and then to win in the last one. Note that before the last contest his rating will be 0.

3)

 

 

{1000000000,1000000000,10000,100000,2202,1}

1000

Returns: 4

 

4)

 

 

{2048,1024,5012,256,128,64,32,16,8,4,2,1,0}

2199

Returns: 0

 

5)

 

 

{61,666,512,229,618,419,757,217,458,883,23,932,547,679,565,767,513,798,870,31,379,294,929,892,173,127,796,353,913,115,802,803,948,592,959,127,501,319,140,694,851,189,924,590,790,3,669,541,342,272}

1223

Returns: 29

 

6)

 

 

{34,64,43,14,58,30,2,16,90,58,35,55,46,24,14,73,96,13,9,42,64,36,89,42,42,64,52,68,53,76,52,54,23,88,32,52,28,96,70,32,26,3,23,78,47,23,54,30,86,32}

1328

Returns: 20

 

类型:dp  难度:2.5

题意:给出一个初始分数X,以及一个数组D,表示每次比赛的分值,按顺序进行比赛,若赢则当前分数加上本次比赛分数,若输则减去,每次分数大于等于2200时,必须在下一次比赛(如果有的话)回到2200一下,分值小于0时,记为0,求分数最多越过2200几次。(如1900->2200,越过2200一次,2200->2199,也算越过2200一次)

分析:一开始考虑为dp,但是因为超过2200的部分,其得分范围可能很大,所以放弃了dp,采用搜索的方法,但是会超时,后来发现,实际上是可以用dp的,因为每次超过2200时,下一回合必须回到2200一下,所以直接跳过一个状态即可,用dp[i][j]记录第i次比赛,当前分值为j时,分数越过2200的最大次数。

遍历每次比赛,每次比赛遍历上一次比赛在0-2200中可能的取值,然后更新本次比赛可能的取值,即dp[i][j] = max(dp[i-1][k]),其中j = k+D[i]或k-D[i]

若k+D[i]>=2200,即加上当前比赛分数后,分值超过2200,那么再分情况讨论:

1、若k+D[i]-D[i+1]<2200,即在下一回合能回到2200一下,合法,那么dp[i+1] = 2+dp[i-1][k]

2、若k+D[i]-D[i+1]>=2200,非法,舍弃

3、若i为最后一次比赛,则dp[i] = 1+dp[i-1][k]

注意:由于k-D[i]有可能小于0,注意将其重置为0,防止数组越界

 

代码:

#include<iostream>
#include<cstring>
#include<cstdio>
#include<string>
#include<vector>
using namespace std;

int dp[60][2210];

class TypoCoderDiv1
{
private:
    vector<int> d;
public:
    int mmax(int a,int b)
    {
        return a>b?a:b;
    }
    int getmax(vector <int> D, int X)
    {
        d.assign(D.begin(),D.end());
        memset(dp,-1,sizeof(dp));
        
        dp[0][X] = 0;
        for(int i=0; i<d.size(); i++)
        {
            for(int j=0; j<2200; j++)
            {
                if(dp[i][j]>=0)
                {
                    int nowa = j+d[i];
                    int nowb = j-d[i];
                    if(nowa>=2200)
                    {
                        if(i+1<d.size())
                        {
                            int tmp = nowa-d[i+1];
                            if(tmp<2200)
                            {
                                if(tmp<0) tmp = 0;
                                dp[i+2][tmp] = mmax(dp[i+2][tmp],dp[i][j]+2);
                            }
                        }
                        else
                        {
                            dp[i+1][j] = mmax(dp[i+1][j],dp[i][j]+1);
                        }
                    }
                    else
                    {
                        dp[i+1][nowa] = mmax(dp[i+1][nowa],dp[i][j]);
                    }
                    if(nowb<0)
                        nowb = 0;
                    dp[i+1][nowb] = mmax(dp[i+1][nowb],dp[i][j]);
                }
            }
        }
        int ans = 0;
        for(int i=0; i<2200; i++)
            ans = mmax(ans,dp[d.size()][i]);
        return ans;
    }
};

int main()
{
    TypoCoderDiv1 t;
    int a[] = {1000000000,1000000000,10000,100000,2202,1};
    vector<int> b;
    for(int i=0; i<6; i++)
        b.push_back(a[i]);
    cout<<t.getmax(b,1000)<<endl;
}


 

你可能感兴趣的:(dp,topcoder)