• 洛谷 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 }

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

  • 相关阅读:
    分享的选择
    @contextmanager 另外一种实现上下文的方法(含yield 生成器)
    Linux ☞ Good good study,day day up
    Linux常用命令
    python 新手遇到的问题
    Pyqt 基础功能
    redis安装使用
    python 对任意文件(jpg,png,mp3,mp4)base64的编码解码
    PHP7.* AES的加密解密
    Ubuntu宝塔面板设置网站 Apache Server API为Apache 2.0 Handler模式
  • 原文地址:https://www.cnblogs.com/yinyuqin/p/13829520.html
Copyright © 2020-2023  润新知