洛谷 P4933 大师(dp)

传送门


解题思路

设dp[i][j]表示选出了第i个电塔,上一个选出的是第j个电塔的方案数。

枚举i,j,转移方程为:

  找一个k,使得h[k],h[j],h[i]构成等差数列,并且k<j。

  dp[i][j]+=dp[j][k];

对于确定的i,j,h[k]是确定的,所以我们可以用vector a[i]的高度为i的编号,k即为枚举a[h[k]]里的元素。

为了防止快乐的RE,

要判断计算出的h[k]是否<0或者>=maxv。

时间复杂度不太会算,看起来像是在O(n^2)到O(n^3)之间,貌似重复元素个数不同时间不同……

有大佬知道的麻烦在评论区留言,万分感谢~

AC代码

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<cmath>
 4 #include<cstdio>
 5 #include<cstring>
 6 #include<vector>
 7 using namespace std;
 8 const int maxn=1005;
 9 const int maxv=20005;
10 const int mod=998244353;
11 int n,h[maxn],dp[maxn][maxn],ans;
12 vector<int> a[maxv];
13 int main()
14 {
15     cin>>n;
16     ans=n;
17     for(int i=1;i<=n;i++) cin>>h[i];
18     for(int i=1;i<=n;i++) {
19         for(int j=1;j<i;j++){
20             dp[i][j]=1;
21             int d=h[i]-h[j];
22             if(h[j]-d<0||h[j]-d>=maxv){
23                 ans=(ans+1)%mod;
24                 continue;
25             }
26             for(int k=0;k<a[h[j]-d].size();k++){
27                 if(a[h[j]-d][k]>=j) break;
28                 else dp[i][j]=(dp[i][j]+dp[j][a[h[j]-d][k]])%mod;
29             }
30             ans=(ans+dp[i][j])%mod;
31         }
32         a[h[i]].push_back(i);
33     }
34     cout<<ans;
35     return 0;
36 }

//明天还上课,困死了,睡觉睡觉………… 

posted @ 2020-10-17 00:28  尹昱钦  阅读(90)  评论(0编辑  收藏  举报