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;
}

浙公网安备 33010602011771号