动态规划——最长上升子序列模型-创新互联

最长上升子序列模型:

给定一个长度为 N 的数列,求数值严格单调递增的子序列的长度最长是多少。

成都创新互联公司专注于广南网站建设服务及定制,我们拥有丰富的企业做网站经验。 热诚为您提供广南营销型网站建设,广南网站制作、广南网页设计、广南网站官网定制、成都小程序开发服务,打造广南网络公司原创品牌,更为您提供广南网站排名全网营销落地服务。

输入格式:

第一行包含整数 N。

第二行包含 N 个整数,表示完整序列。

输出格式:

输出一个整数,表示大长度。

例如:3 1 2 1 8 5 6这个序列的最长递增子序列长度为4(1 2 5 6)。

思路:

f[i]表示以i为结尾的所有上升子序列中最长的那个序列的长度。状态计算:f[i]=f[j]+1,f[j]为i前面的子序列中可以连接到i前面的最长的一个序列(也就是j

代码如下:

#includeusing namespace std;
const int N = 1010;
int f[N], a[N];
int n, res = 1;

int main() {
    cin >>n;

    for (int i = 0; i< n; i++) {
        cin >>a[i];
        f[i] = 1;

        for (int j = 0; j< i; j++)
            if (a[j]< a[i]) {
                f[i] = max(f[i], f[j] + 1);
                res = max(res, f[i]);
            }
    }

    cout<< res;
    return 0;
}
例题:

1.怪盗基德:

假设城市中一共有N幢建筑排成一条线,每幢建筑的高度各不相同。

初始时,怪盗基德可以在任何一幢建筑的顶端。

他可以选择一个方向逃跑,但是不能中途改变方向。

因为滑翔翼动力装置受损,他只能往下滑行(只能从较高的建筑滑翔到较低的建筑)。

他希望尽可能多地经过不同建筑的顶部。

请问,他最多可以经过多少幢不同建筑的顶部。

输入格式:

输入数据第一行是一个整数K,代表有K组测试数据。

每组测试数据包含两行:第一行是一个整数N,代表有N幢建筑。第二行包含N个不同的整数,每一个对应一幢建筑的高度h,按照建筑的排列顺序给出。

输出格式:

对于每一组测试数据,输出一行,包含一个整数,代表怪盗基德最多可以经过的建筑数量。

思路:

我们求出以每个点为结尾的最长上升子序列的长度,就是求出了以每个点为起点向左往下飞的最多建筑数量;

我们求出以每个点为结尾的最长下降子序列的长度,就是求出了以每个点为终点的往右飞的最多建筑数量。

所以我们求出两者取大值即可。

代码如下:

#includeusing namespace std;
const int N = 110;
int a[N], f_up[N], f_down[N];
int K, n;

int main() {
    cin >>K;

    while (K--) {
        cin >>n;
        int max_u = 1, max_d = 1;

        for (int i = 0; i< n; i++) {
            cin >>a[i];
            f_up[i] = f_down[i] = 1;

            for (int j = 0; j< i; j++) {
                if (a[j]< a[i]) { f_up[i] = max(f_up[i], f_up[j] + 1); max_u = max(max_u, f_up[i]); }
                else if (a[j] >a[i]) { f_down[i] = max(f_down[i], f_down[j] + 1); max_d = max(max_d, f_down[i]); }
            }

        }
        cout<< max(max_u, max_d)<< endl;
    }

    return 0;
}

2.登山:

山上一共有N个景点,每个景点有对应的编号。

队员决定按照顺序来浏览这些景点,即每次所浏览景点的编号都要大于前一个浏览景点的编号。

同时队员们还有另一个登山习惯,就是不连续浏览海拔相同的两个景点,并且一旦开始下山,就不再向上走了。

问最多能浏览多少个景点。

思路:

要求的是先上升再下降的最长子序列。

从前往后求一遍上升子序列;

从后往前求一遍上升子序列(相当于从前往后下降)。

然后找出哪个点的上升和下降子序列之和大,答案就是大值减一。

代码如下:

#includeusing namespace std;

const int N = 1010;
int a[N], f_up[N], f_down[N];
int n, res = 1;

int main() {
    cin >>n;

    for (int i = 0; i< n; i++) {
        cin >>a[i];
        f_up[i] = 1;

        for (int j = 0; j< i; j++)
            if (a[j]< a[i])f_up[i] = max(f_up[i], f_up[j] + 1);

    }

    for (int i = n - 1; i >= 0; i--) {
        f_down[i] = 1;

        for (int j = n - 1; j >i; j--)
            if (a[j]< a[i])f_down[i] = max(f_down[i], f_down[j] + 1);

        res = max(res, f_down[i] + f_up[i]);
    }

    cout<< res - 1;

    return 0;
}

你是否还在寻找稳定的海外服务器提供商?创新互联www.cdcxhl.cn海外机房具备T级流量清洗系统配攻击溯源,准确流量调度确保服务器高可用性,企业级服务器适合批量采购,新人活动首月15元起,快前往官网查看详情吧


分享文章:动态规划——最长上升子序列模型-创新互联
分享URL:http://hbruida.cn/article/dchpcc.html