http://acm.hdu.edu.cn/showproblem.php?pid=4504
题目大意:
中文都看得懂。不过我是看hint才正确理解什么意思的。开始的时候理解错了。
解题思路:
给定时间最多是600,最多进攻次数600/15=40次,我方进攻次数40/2=20次。如果深度搜索多少种情况,
那么时间复杂度是O(3^20),直接就超时了。
我知道要动态规划,但是自己dp不行,所以就看了网上别人的解题报告。
dp[i][j]=dp[i-1][j-1]+dp[i-1][j-2]+dp[i-1][j-3] ;表示第i次,得j分的方案
先将得分方案预处理(预处理时间是O(20*60))。求答案的时候再将进攻t次,大于A、B分数之的方案加起来(时间复杂度最坏O(60))。
AC代码:
1 #include<cstdio> 2 #include<cstring> 3 4 #define TIMES 21//最多打600/15/2=20次 5 #define SCORE 61//做多得分20*3=60分 6 7 typedef __int64 LL; 8 9 //dp[i][j] 表示第i次,投j分的情况 dp[i][j]=dp[i-1][j-1]+dp[i-1][j-2]+dp[i-1][j-3] 10 int dp[TIMES][SCORE]; 11 12 void dynamic(){ 13 // memset(dp, 0, sizeof(dp)); 14 dp[0][0] = 1; 15 for(int i = 1; i < TIMES; ++i){ 16 dp[i][i] = dp[i - 1][i - 1]; 17 dp[i][i + 1] = dp[i - 1][i - 1] + dp[i - 1][i]; 18 19 for(int j = i + 2; j <= i * 3; ++j){ 20 dp[i][j] = dp[i - 1][j - 1] + dp[i - 1][j - 2] + dp[i - 1][j - 3]; 21 } 22 } 23 } 24 25 int main(){ 26 dynamic();//预处理 27 int a, b, t; 28 while(~scanf("%d%d%d", &a, &b, &t)){ 29 t /= 15;// 30 b += t / 2;//B队的最终得分 31 t = (t + 1) / 2;//A队还能进攻t次 32 a = b - a + 1;//计算A队至少还差多少分就能赢得比赛 33 34 if(a < 0) a = 0;//说明A已经赢得比赛 那就把所有的情况加起来 35 36 LL ans = 0; 37 for(int i = a; i <= t * 3; ++i){//A队进攻t次数 分数>=a的情况加起来 38 ans += dp[t][i]; 39 } 40 printf("%I64d ", ans); 41 } 42 return 0; 43 }