hdu - 4972 - A simple dynamic programming problem(数学 + dp)

题意:NBA比赛。两方共N次进球(N<=100000),不管哪方,进一个球(得分仅仅可能为1。2,3),就记录一次(记两队分数差的绝对值),问最后两队的比分有多少种。

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4972

——>>知道最后的比分差k,怎么求得比分呢?设分数较低的一方的最后分数为x。则还有一方的最后分数为x + k,设两方最后总分和为S。则x  = (S - k) / 2。可得两方的比分。。所以。仅仅要知道最后两方的总分和,就能够确定两方比分。。

于是。问题转化成求最后两方总分和有多少种。

知道了双分总分和,能够求出x : x + k,还有x + k : x,因此,假设x != x +k 即 k ! = 0时。最后结果应乘2。

状态:dp[i]表示前 i 次进球后两方总分和的种数

状态转移方程:dp[i] = dp[i - 1] + 1(当(diff[i] == 1 && diff[i - 1] == 2) || (diff[i] == 2 && diff[i - 1] == 1) 时)

边界:dp[0] = 1, diff[0] = 0

注:上一次比分差为2,现要达比分差为1,则败者进1分或者进3分。此时可产生2种总分和。。上一次比分差为1,当前比分差为2同理。。

提交G++使用abs(int)会CE(查了一下MinGW里面的cmath,abs确实没有提供 int 參数)。C++不会(翻了下MSDN,提供的參数是有 int 的)。。一直对整数求绝对值用abs,用浮点数求绝对值用fabs的我,好囧。。

敲打

#include <cstdio>
#include <cmath>

using std::abs;

int main()
{
    int T, N, diff, kase = 0;

    scanf("%d", &T);
    while (T--)
    {
        int dp = 1, last = 0;
        bool ok = true;
        scanf("%d", &N);
        while (N--)
        {
            scanf("%d", &diff);
            if (!ok) continue;
            if (abs(diff - last) > 3 || (diff == last && diff != 1))
            {
                ok = false;
            }
            else
            {
                if ((diff == 2 && last == 1) || (diff == 1 && last == 2))
                {
                    dp++;
                }
                last = diff;
            }
        }
        if (diff != 0)
        {
            dp <<= 1;
        }
        printf("Case #%d: ", ++kase);
        ok ?

printf("%d\n", dp) : puts("0"); } return 0; }



posted @ 2017-08-05 08:28  jzdwajue  阅读(133)  评论(0编辑  收藏  举报