SRM 501 DIV1 500pt(DP)

题目简述

给定一个长度为n的序列,每个数值的范围为[-1,40],-1可以替换成0~40之间的数,要求你求出符合以下条件的序列有多少个?

1、每个数都是0~40之间的数

2、对于每一个数A[i],都需要小于等于前面所有数的算术平均值,及 对于 i, 1 <= i < N, 需要满足 A[i] <= (A[0] + A[1] + ... + A[i-1]) / i

3、序列中不存在三个连续的数刚好是严格递减的

题目做法

dp[i][j][k][f]表示当前第i个数和为j,第i-1个数为k,f表示i-2是否小于i-1的符合要求的序列总个数,时间复杂度为O(n^5)

代码:

 1 int dp[45][2000][45][2];
 2 class FoxAverageSequence
 3 {
 4 public:
 5     int theCount(vector <int> seq)
 6     {
 7         memset(dp, 0, sizeof(dp));
 8         int n = seq.size();
 9         if (seq[0] == -1)
10             for (int i = 0; i <= 40; i++) dp[0][i][i][0] = 1;
11         else dp[0][seq[0]][seq[0]][0] = 1;
12         for (int i = 1; i < n; i++)
13             for (int j = 0; j <= 1600; j++)
14                 for (int k = 0; k <= 40; k++)
15                     for (int f = 0; f < 2; f++)
16                     {
17                         int num = seq[i];
18                         if (dp[i - 1][j][k][f])
19                         {
20                             int tj = j + num, tf = num < k ? 1 : 0;
21                             if (num == -1)
22                             {
23                                 for (int a = 0; a <= 40; a++)
24                                 {
25                                     tf = a < k ? 1 : 0;
26                                     tj = j + a;
27                                     if (f && tf) continue;
28                                     if (a * i > j) break;
29                                     dp[i][tj][a][tf] += dp[i - 1][j][k][f];
30                                     dp[i][tj][a][tf] %= MOD;
31 
32                                 }
33 
34                             }
35                             else
36                             {
37                                 if (f && tf) continue;
38                                 if (num * i > j) continue;
39                                 dp[i][tj][num][tf] += dp[i - 1][j][k][f];
40                                 dp[i][tj][num][tf] %= MOD;
41                             }
42                         }
43                     }
44         int ans = 0;
45         for (int i = 0; i <= 1600; i++)
46             for (int j = 0; j <= 40; j++)
47             {
48                 ans += dp[n - 1][i][j][0];
49                 ans %= MOD;
50                 ans += dp[n - 1][i][j][1];
51                 ans %= MOD;
52             }
53             printf("%d\n",ans);
54         return ans;
55 
56     }
57 };

 

posted on 2014-11-21 17:10  仗剑奔走天涯  阅读(357)  评论(0编辑  收藏  举报

导航