http://acm.hdu.edu.cn/showproblem.php?pid=4504
题目大意:
篮球赛假如我们现在已经知道当前比分 A:B,A代表我方的比分,B代表对方的比分,现在比赛还剩下t秒时间。我们简单的认为双方各自进攻一次的时间皆固定为15秒(不到15秒则进攻不得分),且为交替进攻,即我方进攻一次,接着对方进攻,依次循环。
进攻有三种选择方式:(这里不考虑命中率)
1、造犯规,(假设都两罚一中)得1分;
2、中距离投篮 得2分;
3、三分球 得3分。
为了简化问题,假设在对方回合,由于我方防守比较好,只让对手得1分,且为固定,即对方的进攻回合就为每回合得1分。现在比赛进入最后关头,接下来第一个回合是我方进攻,现在威威猫想要知道教练有多少种不同的选择能使我方可能赢得比赛(可能的意思就是不考虑命中率的情况)。
思路:
dp,dp[i][j]为第i次进攻分数为j的最大方法数 。
则显然dp[i][j]=dp[i-1][j-1]+dp[i-1][j-2]+dp[i-1][j-3];
一开始数组开太小哭了啊。啊啊啊。
#include<cstdio>
#include<cstring>
using namespace std;
const int MAXN=80;
int dp[25][MAXN];//dp[i][j]为第i次进攻分数为j的最大方法数
int main()
{
memset(dp,0,sizeof(dp));
dp[1][1]=dp[1][2]=dp[1][3]=1;
for(int i=1;i<=20;i++)
{
for(int j=1;j<=60;j++)
{
if(j>1) dp[i][j]+=dp[i-1][j-1];
if(j>2) dp[i][j]+=dp[i-1][j-2];
if(j>3) dp[i][j]+=dp[i-1][j-3];
}
}
int a,b,t;
while(~scanf("%d%d%d",&a,&b,&t))
{
int t1=t/15;
t1=(t1+1)>>1;
if(t1==0)
{
if(a>b)
printf("1\n");
else
printf("0\n");
continue;
}
int t2=t/15-t1;
int begin=b-a+t2+1;
//printf("%d\n",begin);
if(begin<0) begin=0;
int en=t1*3;
__int64 ans=0;
for(int i=begin;i<=en;i++)
{
ans+=dp[t1][i];
}
printf("%I64d\n",ans);
}
return 0;
}