• 古韵之乞巧 题解 dp题


    【noip模拟赛1】古韵之乞巧
     

    描述

     

    闺女求天女,更阑意未阑。

    玉庭开粉席,罗袖捧金盘。

    向月穿针易,临风整线难。

    不知谁得巧,明旦试相看。

    ——祖咏《七夕》

    女子乞巧,是七夕的重头戏。古时,女子擅长女红被视为一种重要的德行。所以女孩子们纷纷在七夕这天祈求上天,是自己变得更加灵巧。仰头凝视,以虔诚的心去膜拜桂魄;双手合十,用坚定信念去盼望未来,祈求能有更出众的才能。一根针、一丝线、一轮月、一束影,组成了一个简单的乞巧仪式。

    “年年岁岁花相似,岁岁年年人不同。”千百年后的今天,女孩子们更加看重自己的才华与能力。韵哲君参加了一个新乞巧活动:

    韵哲君发现自己的面前有一行数字,当她正在琢磨应该干什么的时候,这时候,陈凡老师从天而降,走到了韵哲君的身边,低下头,对她耳语了几句,然后飘走了。

    陈凡老师说了什么呢,且听下回分解。

    接上回书,陈凡老师原来对韵哲君说了这些话:“还记得我传授给你的不下降子序列吗?你现在只要找出一定长度的不下降子序列的种数,你就完成任务了。”

    输入

     

    第一行有两个整数N(0<N<=100),M(0<M<=20);

    N表示给出多少个整数,M表示给出的定长;

    第二行有N个整数,对于每个数字(-10000<=T[i]<=10000)。

    输出

     

    输出一个整数,在给出的数列中定长不下降子序列的种数。

    输入样例 1 

    10 5
    1 2 3 4 5 6 7 8 9 10

    输出样例 1

    252

    网址:http://dingbacode.com/contest/19/problem/D

    不下降子序列,就是任选几个数,后面数大于等于前面的数,就是 “不下降子序列” 了。

    dp题,类似于背包,开一个数组 dp[] dp[i]代表以i为结尾的序列 当前长度 的个数(当前长度由dp的外循环确定,当外循环到5时,即长度到了5)。

    很明显的是,当长度为1时,dp的值均为1,在读入值得时候顺便完成。

    然后是核心代码: 

    for(int i=2;i<=m;i++)       //做一个循环,2 到 m ,代表长度从2到5的递推(1 已确定)

    {
      for(int k=n;k>i-1;k--)   //更新从 n 到 i 的dp,小于 i 的由于 当长度为i时 ,必为0,所以无需更新。注意反向更新,理由同背包,这是01背包而非完全背包
      {
          dp[k]=0;     // 将该数归零,因为其后会受其影响的已经确定,以k为末尾的序列已经累加到后面的 dp 中。
          for(int j = i-1;j < k; j++)    // 遍历k前面的dp,因为 i-1 前面的数,在长度为 i -1 时必然为0,所以无需累加到 dp[k] 上
          {
            if(a[k]>=a[j])    //判断是否不下降
              dp[k]+=dp[j];  //将长度为 i-1 的序列连上 k ,成为 i 长度的序列,累加到 dp[k] 上。
          }
      }
    }

    然而这样做之后,还是会有一个点 wa,

    这是后就要想到数大小的问题,将 dp 和 sum开为long long 后,就ac了。

    
    
    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    #include <time.h>
    #include <string>
    #include <map>
    #include <stack>
    #include <vector>
    #include <set>
    #include <queue>
    #define INF 0x3f3f3f3f
    using namespace std;
    const int N=105;
    long long dp[N];
    int n,m,a[N];
    
    
    int main()
    {
         // freopen("input.txt","r",stdin);
          cin>>n>>m;
          for(int i=1;i<=n;i++)
          {
                cin>>a[i];
                dp[i]=1;
          }
          for(int i=2;i<=m;i++)
          {
                for(int k=n;k>i-1;k--)
                {
                      dp[k]=0;
                      for(int j=i-1;j<k;j++)
                      {
                            if(a[k]>=a[j])
                                  dp[k]+=dp[j];
                      }
                }
          }
          long long ans=0;
          for(int i=m;i<=n;i++)
                ans+=dp[i];
          cout<<ans;
          return 0;
    }
  • 相关阅读:
    MySQL客户端mysqladmin命令
    13 Linux磁盘管理
    12 Linux软件管理
    11 Linux压缩打包
    09 Linux输入输出
    08 LinuxACL控制
    07 Linux特殊权限
    06 Linux基本权限
    05 Linux用户管理
    04 Linux文件编辑
  • 原文地址:https://www.cnblogs.com/zgncbsylm/p/10579859.html
Copyright © 2020-2023  润新知