直入主题
由于手残,将帖子一次次的删除所以就不想搞那些花里胡哨的了
引子:
本周我们学习了,动态规划。由于本人太菜就想来写篇帖子,加强巩固一下。
就是太菜了
第一部分概念:
主要分为:
- 状态和状态变量
- 阶段和阶段变量
- 策略和最优策略
- 状态转移方程
戳我
还有不懂请参见信息奥赛一本通
其实DP就是一个类似递推的算法。
看完了概念我们就开始上代码:
第一题:最长上升子序列(时间复杂度O)
题
题目描述:
给定一个序列,从中选取若干个数,使得这一组数组成的序列a满足 i < j 且 a[i] < a[j],求这个序列的最长长度。
#include <cstdio>
const int MAXN = 5005;
int a[MAXN], dp[MAXN];
int main() {
int n;
scanf ("%d", &n);
int ans = 0, s = 0;
for(int i = 1; i <= n; i++) {
scanf("%d", &a[i]);
dp[i] = 1; //初始化
for(int j = 1; j < i; j++) {
if(a[i] > a[j] && dp[j] + 1 > dp[i]) {
dp[i] = dp[j] + 1;
}
}
if(dp[i] > ans) {
ans = dp[i];
s = i;//转移答案
}
}
printf("%d\n", ans);
return 0;
}
那么就开始解释一下了。首先,我们定义一个DP数组,而dp[i]表示以i结尾的最长上升子序列的长度,这就是所谓的状态。之后可以用两重循环,接着循环扫了一遍之后,来找出当前以i结尾最长上升子序列,判断一下,之后就将已经找到的最长上升子序列的长度赋值。依次循环得到最优解 循环结束——本题结束。
那么你如果想知道(n*logn)的解法。
就自己想想吧,实在不行我也没办法,总之,等下次就会登场了。
那么问题来了:什么时候会用到动态规划呢?
经GM权威讲解:我们知道了当一个问题的状态转移方程具有最优子结构与重叠子问题,则其可用动态规划求解。
这就与贪心形成了鲜明的对比!!
那么我们开始下一道题!
最长上升子序列の输出序列
题目大门
题目描述:
给定一个整数序列A1A2A3….An。求它的一个递增子序列,使子序列的元素个数尽量多,元素不一定要求连续。
(特别注意这里:
输出格式
第1行:1个整数k,表示最长上升子序列的长度。
第2行:k个用单个空格分开的整数,表示找到了最长上升子序列。如果有多个长度等于k的子序列,则输出最靠前的1个。
)
那么上代码!(WA代码)
#include <cstdio>
int prev[1005];
const int MAXN = 100005;
int a[MAXN], dp[MAXN];
using namespace std;
void print(int i){
if(prev[i]==i){
printf("%d",a[i])