070day(动态规划思路,例题(最长上升子序列)和流操纵算子)

来源:互联网 发布:mysql 查询临时表 编辑:程序博客网 时间:2024/05/30 05:30

172210704111-陈国佳总结《2017年12月19日》【连续070天】

标题:动态规划思路,例题(最长上升子序列)和流操纵算子;

内容:
A.动规解题的一般思路:
1.将原问题分解为子问题:
1)分解

2)保存子问题的解;

2.确定状态:整个问题的复杂度为状态数目乘以计算每个状态所需要的时间;

3.确定一些初始状态(边界状态)的值;

4.确定状态转移方程;

动规所能解决问题的特点:

1)问题具有最优子结构性质;

2)无后效性;


B.例题:最长上升子序列:

描述
一个数的序列bi,当b1 < b2 < ... < bS的时候,我们称这个序列是上升的。对于给定的一个序列(a1a2, ..., aN),我们可以得到一些上升的子序列(ai1ai2, ..., aiK),这里1 <= i1 < i2 < ... < iK <= N。比如,对于序列(1, 7, 3, 5, 9, 4, 8),有它的一些上升子序列,如(1, 7), (3, 4, 8)等等。这些子序列中最长的长度是4,比如子序列(1, 3, 5, 8).

你的任务,就是对于给定的序列,求出最长上升子序列的长度。
输入
输入的第一行是序列的长度N (1 <= N <= 1000)。第二行给出序列中的N个整数,这些整数的取值范围都在0到10000

描述

一个数的序列bi,当b1 < b2 < ... < bS的时候,我们称这个序列是上升的。对于给定的一个序列(a1, a2, ..., aN),我们可以得到一些上升的子序列(ai1, ai2, ..., aiK),这里1 <= i1 < i2 < ... < iK <= N。比如,对于序列(1, 7, 3, 5, 9, 4, 8),有它的一些上升子序列,如(1, 7), (3, 4, 8)等等。这些子序列中最长的长度是4,比如子序列(1, 3, 5, 8).

你的任务,就是对于给定的序列,求出最长上升子序列的长度。
输入
输入的第一行是序列的长度N (1 <= N <= 1000)。第二行给出序列中的N个整数,这些整数的取值范围都在0到10000。
输出
最长上升子序列的长度。
样例输入
7
1 7 3 5 9 4 8
样例输出
4

思路:
1.找子问题:

“求以ak(k=1,2,3......N)为终点的最长上升子序列的长度

一个上升子序列中最右边的数为“终点”;

虽然子问题和原问题形式上并不完全一样,但所有子问题的最大解就是整个问题的解;

2.确定状态:
k就是状态,状态K对应的值便是ak为终点的最长上升子序列的长度,状态共有N个;

3.状态转移方程:
初始状态:maxLen(1)=1

maxLen(k)=max{maxLen(i):1<=i<k且ai<ak且k!=1}+1

若找不到这样的i,则maxLen(k)=1;

#include<iostream>#include<cstring>#include<algorithm>using namespace std;const int MAXN=1010;int a[MAXN];int maxLen[MAXN];int main(){int N; cin>>N;for(int i=1;i<=N;++i){cin>>a[i];  maxLen[i]=1;}for(int i=2;i<=N;++i){for(int j=1;j<i;++i)  if(a[i]>a[j])     maxLen[i]=max(maxLen[i],maxLen[j]+1);}cout<<*max_element(maxLen+1,maxLen+N+1);return 0;}
我在devC++上虽然编译成功,但运行时发生了问题,又用了vs调试,网上说是符号集的问题,但是按照他们的方法并没有解决问题,

大概是win32和64程序的不兼容;


C.流操纵算子:

1.整数流的基数:dec,oct,hex.setbase;

2.浮点数的精度:precision,setprecision;

3.设置域宽:setw,width;

4.用户自定义的流操纵算子;

#include<iomanip>

2.precision是成员函数:

cout.precision(5);

setprecision是流操作算子:

cout<<setprecision(5);

功能相同;

非定点方式输出:
指定输出浮点数的有效位数;

定点方式输出时:

指定输出浮点数的小数点后的有效数位(小数点必须出现在个位数后面)

定点:cout<<setiosflags(ios::fixed)<<

cout<<fixed<<

取消定点:cout<<resetiosflags(ios::fixed)<<

科学记数法输出:cout<<scientific<<

(e+00x)=10^x;

4.设置域宽:

cin>>setw(4);或cin.width(5);

cout<<setw(4);或cout.width(5);

域宽设置有效性是一次性的,在每次读入和输出之前都要设置宽度;

注意:宽度只限制下限,如输入4个字符,宽度为5,则最前空一个,输入6个字符,则正常输入6个字符;

<<setfill('*')<<     //宽度不足用*来填补,不用空格;

<<showops<<       //非负数显示正号;

<<noshowops<<   //非负数不显示正号;

<<left/right/internal<<     //左/右对齐,宽度不足时,右/左/中(正负号和数值中间)用填充字符填充;

 5.用户自定义流操纵算子:

#include<iostream>#include<iomanip>using namespace std;ostream&tab(ostream&output){return output<<'\t';}int main(){cout<<"aa"<<tab<<"bb"<<endl;}
输出aa        bb

 由运算符重载的知识可得<<和>>经过了重载,

因此,流操纵算子其本质上是函数;



明日计划:学习动态规划;