A simple dynamic programming problem
Time Limit: 2000/1000 MS (Java/Others)
Memory Limit: 65536/65536 K (Java/Others)
Problem Description
Dragon is watching NBA. He loves James and Miami Heat.
Here’s an introduction of basketball game:http://en.wikipedia.org/wiki/Basketball. However the game in Dragon’s version is much easier:
“There’s two teams fight for the winner. The only way to gain scores is to throw the basketball into the basket. Each time after throwing into the basket, the score gained by the team is 1, 2 or 3. However due to the uncertain factors in the game, it’s hard to predict which team will get the next goal”.
Dragon is a crazy fan of Miami Heat so that after each throw, he will write down the difference between two team’s score regardless of which team keeping ahead. For example, if Heat’s score is 15 and the opposite team’s score is 20, Dragon will write down 5. On the contrary, if Heat has 20 points and the opposite team has 15 points, Dragon will still write down 5.
Several days after the game, Dragon finds out the paper with his record, but he forgets the result of the game. It’s also fun to look though the differences without knowing who lead the game, for there are so many uncertain! Dragon loves uncertain, and he wants to know how many results could the game has gone?
Input
The first line of input contains only one integer T, the number of test cases. Following T blocks, each block describe one test case.
For each test case, the first line contains only one integer N(N<=100000), which means the number of records on the paper. Then there comes a line with N integers (a1, a2, a3, … , an). ai means the number of i-th record.
Output
Each output should occupy one line. Each line should start with “Case #i: “, with i implying the case number. Then for each case just puts an integer, implying the number of result could the game has gone.
Sample Input
2
2
2 3
4
1 3 5 7
Sample Output
Case #1: 2
Case #2: 2
source
题意
龙喜欢看篮球,每次有人进球都记下两队比分的差值,比如热火队得分20,对手得分15,则记5,热火20对手15也记5。。。之后给一个从开始到结束序列,问结果的比分有多少种可能。感觉题目比较坑的是没说明白什么时候记录,题中说的是after each throw,然后记录,我理解的就是每次投球后记录,实际上是每次得分后记录,wa了我好多发(大概是我想多了),首先要判断输入是否合法,如果存在连续两个记录的差值大于3,或者连续两个记录相等且不等于1,则输入非法。因为每次最多得3分,所以差值不会大于3,而当一个队获得2分之后赶超的情况下会得到两个连续的1。输入合法的情况下,我们维护一个变量ans,表示可能出现的比分中较小的那一个的可能数,初始化为1,之后从前往后扫,每次扫到1 2或者2 1时ans+1,举个例子,假如现在可能的比分有1:2 2:3 ans=2,下一个状态比分的差值为2,则下一个状态可能的比分有 1:3 2:4(1分队伍获得3分赶超) 2:4(3分队伍获得1分) 3:5,较小的分值可能为 1 2 3,ans=3。扫到尾部后看序列最后一项是否为0,为0的话表示最终为平局,直接输出ans,否则输出ans*2,1:3和3:1是不同的。AC代码如下
#include <cstdio>
#include <algorithm>
#include <cmath>
using namespace std;
int T,Mark;
int N,a[100005];
int ans;
int main()
{
scanf("%d",&T);
for(int cas=1;cas<=T;cas++)
{
scanf("%d",&N);
ans=1;Mark=0;
scanf("%d",&a[0]);
for(int i=1;i<N;i++)
{
scanf("%d",&a[i]);
if((a[i]==a[i-1]&&a[i]!=1)||abs(a[i]-a[i-1])>3)
Mark=1;
}
if(Mark)
{
printf("Case #%d: 0\n",cas);
continue;
}
for(int i=1;i<N;i++)
{
if((a[i]==2&&a[i-1]==1)||(a[i]==1&&a[i-1]==2))
ans++;
}
if(a[N-1]==0)
printf("Case #%d: %d\n",cas,ans);
else
printf("Case #%d: %d\n",cas,2*ans);
}
return 0;
}