分析: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