分析:d[i][j]表示前i回合获得j分的方法数。
d[i][j]=d[i-1][j-1]+d[i-1][j-2]+d[i-1][j-3]。
我方最多进攻20次,每次得3分,最多20*60的状态量。
#include<iostream>
using namespace std;
//dp[i][j]代表我方第i轮获得j分的种类数
__int64 dp[26][70]; //最大600s,600/15=40,40/2=20,最多20轮,最多得分20*3。
void Init() //初始打表
{
int i,j;
memset(dp,0,sizeof(dp));
dp[1][1]=dp[1][2]=dp[1][3]=1;
for(i=2;i<=20;i++)
for(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];
}
}
void sovle(int A,int B,int t)
{
int k,ta,tb,diff,i;
__int64 ans;
k=t/15; //还可以进攻的轮数
ta=(k+1)/2; //我方进攻轮数,一开始我方进攻
tb=k-ta; //对方进攻轮数
if(ta==0)
{
if(A>B)
puts("1"); //已经赢了,算一次
else
puts("0");
return ;
}
B+=tb; //对方每轮获得1分,算总分
diff=B-A+1; //我方还差对方多少分才可以获胜且不是平局
if(diff<0) //已经获胜就设为0
diff=0;
ans=0;
for(i=diff;i<=ta*3;i++) //只要最终(第ta轮)比对方分数高都可以
ans+=dp[ta][i];
printf("%I64d\n",ans);
}
int main()
{
int A,B,t;
Init();
while(scanf("%d%d%d",&A,&B,&t)==3)
sovle(A,B,t);
return 0;
}
原文地址:http://blog.csdn.net/a809146548/article/details/46401977