IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 【Java题解】洛谷题目P3205合唱队-区间动态规划解法 -> 正文阅读

[数据结构与算法]【Java题解】洛谷题目P3205合唱队-区间动态规划解法

题目描述:

[HNOI2010]合唱队 - 洛谷https://www.luogu.com.cn/problem/P3205

题目信息提取:

?????????这个题目要求我们按照某种顺序将这个队伍中的所有人按照从左到右的顺序去排队,其实题目中的很多无用信息可以忽略,总结为,寻找某种数列,将这个数列按照从左到右的顺序依次进行排列,排列规则是,如果当前数字大于前一个已经排列完的数,那么他就放在新的当前排列的数列的最后面,如果他小于前一个已经排列玩的数字,那么他就放在当前排列的数列的最前面,看下面一个例子:

例如 初始数列为 33 22 11 44 那么他的排列顺序就是

因为22<33 所以 22 33

因为11<22 所以 11 22 33

因为44>11 所以 11 22 33 44

题目思路归纳:

? ? ? ?我们了解了基本的规则以后,看题目,题目给出一个期望得到的排列后的数列,让我们求出有几种默认的数列排放顺序可以经过排序后得到期望数列。所以我们可以考虑假如 我们要求的 期望数列为 11 22 33 44既然是动态规划,我们将应该先去总结出有无状态之间的转换关系,即状态转移方程,11 22 33 44的初始队列数量如何从一个子结构转化出来,11 22 33 44 他既可能是 22 33 44 加入了11也可能是11 22 33 加入了44,只有这两种可能,因为最新加入的数字一定在队列的最左侧或者是最右侧这句话是重点所以标红,所以我们知道了状态转移的规则,即当前状态一定是从他的左侧不包含最左侧数字的最优子结果和右侧不包含右侧数字的最优子结果转化而来的,这句话的理解非常重要,但是他是如何转化的呢?

????????还是看11 22 33 44 这个例子假如 11 22 33 44 是从11 22 33转化来的,那么数列最右侧的数字一定大于他的前一个数字,否则不成立,即不可能转化,那么他的前一个数字会在哪呢,其实同理就知道,他的前一个数字肯定就是11,33其中的某一个,这两种情况都可能如果是11先排序然后44排序,可以看到情况符合条件是成立的,例如是33排序后44排序,情况也是成立的,所以这两种情况都可以排列出我们要求的顺序,所以这两种情况相加就是44从右侧加进来的情况的数量,那么还有一种情况就是从22 33 44转化来的,即11是最后排序的,那么我们再来讨论11,11也有两种情况,即22和44都有可能是在11之前加入的,假如11小于22,那么22是最后加入的情况也是成立的,假如11小于 44,那么11最后加入的情况也是成立的,我们可以看到当前的数列也是满足这个要求的,所以同理11最后加入的情况的数量就等于22加入的数量加上44加入的数量之和,我们讨论完了这两种情况,不存在其他的情况了,所以11 22 33 44 的所有初始队列种类就是两者之和:我们有了思路就可以总结转台转移方程了,

这里我们使用两个数组来表示left[i][j]表示在下标i-j的这个数列中,最后加入的是i的种类数目而right[i][j]反之.

状态转移方程:

left[i][j] += left[i+1][j] when num[i] < num[i+1] eg:num是期望数列

left[i][j] += right[i+1][j] when num[i]<num[j]?

right[i][j] += right[i][j-1] when num[j]>num[j-1]

right[i][j] += left[i][j-1] when num[j]>num[i]?

代码书写:

? ? ? ? 我们知道了状态转移方程也就基本知道了代码结构了,但是还有一些细节需要注意,例如状态的初态和循环测顺序,首先我门看循环顺序,我们要确定循环的顺序首先看状态转移方程中状态之间的关系,在第一个和第二个状态转移方程中我们都需要i+1时的状态,所以我们可以确定i需要逆序递减求值,在2,3中可以看到都需要j-1的状态所以可以确定j需要递增,所以我们可以确定i的循环要从n开始逐渐递减,j要从i+1开始逐渐递增,来不断的扩展子状态的范围,然后我们需要确认初态,我们要给left[i][j]或者是right[i][j]其中的任何一个赋值1以确保任意值不会为0,只能赋值其中一个,因为当只有一个数时,它只能是从左边进或者是右边进,互相矛盾,所以最终的代码为:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class Main {
    public static void main(String[] args) throws IOException {
        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
        int n = Integer.parseInt(reader.readLine());
        String[] intStr = reader.readLine().split(" ");
        int[] ans = new int[n];
        for(int i = 0;i<n;i++){
            ans[i] = Integer.parseInt(intStr[i]);
        }
        int[][] left = new int[n][n];
        int[][] right = new int[n][n];
        for(int i = 0;i<n;i++){
            left[i][i] = 1;
        }
        for(int i = n-1;i>=0;i--){
            for(int j = i+1;j<n;j++){
                if(ans[i]<ans[j])
                    left[i][j] +=right[i+1][j];
                if(ans[i]<ans[i+1])
                    left[i][j] +=left[i+1][j];
                if(ans[j]>ans[j-1]){
                    right[i][j]+=right[i][j-1];
                }
                if(ans[j]>ans[i])
                    right[i][j] +=left[i][j-1];
                right[i][j]%=19650827;
                left[i][j]%=19650827;
            }
        }
        System.out.println((left[0][n-1]+right[0][n-1])%19650827);
    }

}

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-07-04 23:13:18  更:2022-07-04 23:14:35 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 23:35:10-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码