DP 1

最长上升子序列

int mx = 1;    // 找出所计算的f[i]之中的最大值,边算边找
    for (int i = 0; i < n; i++) {
        f[i] = 1;    // 设f[i]默认为1,找不到前面数字小于自己的时候就为1
        for (int j = 0; j < i; j++) {
            if (w[i] > w[j]) f[i] = max(f[i], f[j] + 1);    // 前一个小于自己的数结尾的最大上升子序列加上自己,即+1
        }
        mx = max(mx, f[i]);
    }

    cout << mx << endl;

最长公共子序列

for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            if(s1[i]==s2[j])
                f[i][j]=f[i-1][j-1]+1;
            else {
                f[i][j]=max(f[i-1][j],f[i][j-1]);
            }    
        }
    }
    cout<<f[n][m]<<endl;

最长公共上升子序列

f[i][j]代表所有a[1 ~ i]和b[1 ~ j]中以b[j]结尾的公共上升子序列的集合;
f[i][j]的值等于该集合的子序列中长度的最大值;

maxv是满足a[i] > b[k]的f[i - 1][k] + 1的前缀最大值。
可以直接将maxv提到第一层循环外面,减少重复计算,此时只剩下两重循环。

    for (int i = 1; i <= n; i ++ )
    {
        int maxv = 1;
        for (int j = 1; j <= n; j ++ )
        {
            f[i][j] = f[i - 1][j];
            if (a[i] == b[j]) f[i][j] = max(f[i][j], maxv);
            if (a[i] > b[j]) maxv = max(maxv, f[i - 1][j] + 1);
        }
    }

    int res = 0;
    for (int i = 1; i <= n; i ++ ) res = max(res, f[n][i]);

拦截导弹

#include<sstream>
#include<iostream>
#include<algorithm>
using namespace std;
const int N=1010;
int n,h[N],f[N],q[N];

int main(){
    string line;
    getline(cin, line);
    stringstream ssin(line);
    while (ssin >> h[n]) n ++ ;
    while (ssin >> h[n]) n ++ ;
    int res = 0, cnt = 0;
    for (int i = 0; i < n; i ++ ){
        f[i] = 1;
        for(int j=0;j<i;j++)
            if(h[i]<=h[j])
                f[i] = max(f[i], f[j] + 1);
        res = max(res, f[i]);
        int k = 0;
        while (k < cnt && q[k] < h[i]) k ++ ;//q记录系统尾巴的导弹高度
        if (k == cnt) q[cnt ++ ] = h[i];//k到cnt了,q[cnt-1]变成当前这套系统的尾巴
        else q[k] = h[i];//没到,换个尾巴
    }
    printf("%d\n", res);
    printf("%d\n", cnt);
    
    return 0;
}
389 207 155 300 299 170 158 65
组一 389 207 155 65 组二 300 299 170 158

一套防御系统的导弹拦截高度要么一直 严格单调 上升要么一直 严格单调 下降。

迭代加深+普通 541ms 时间O(n2^n) 空间O(n)
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

const int N = 60;

int n;
int h[N];
int up[N], down[N];

bool dfs(int depth, int u, int su, int sd) {
    // depth 序列上限, su, sd, u 上一个数或者下一个数
    if (su + sd > depth) return false;  // 9 > 8, 深度从0开始
    if (u == n) return true;

    // 枚举所有选法

    // 枚举上升子序列
    bool flag = false;
    for (int i = 1; i <= su; i ++) // 上升子序列
        if (up[i] < h[u]) {
            int t = up[i];
            up[i] = h[u];
            if (dfs(depth, u + 1, su, sd)) return true;
            up[i] = t;
            flag = true;
            break;
        }

    if (!flag) {
        up[su + 1] = h[u];
        if (dfs(depth, u + 1, su + 1, sd)) return true; 
    }

    // 枚举下降子序列
    flag = false;
    for (int i = 1; i <= sd; i ++)
        if (down[i] > h[u]) {
            int t = down[i];
            down[i] = h[u];
            if (dfs(depth, u + 1, su, sd)) return true;
            down[i] = t;
            flag = true;
            break;
        }

    if (!flag) {
        down[sd + 1] = h[u];
        if (dfs(depth, u + 1, su, sd + 1)) return true;
    }

    return false;
}


int main() {

    while (cin >> n, n) {
        for (int i = 0; i < n; i ++) cin >> h[i];

        int depth = 0;
        while (!dfs(depth, 0, 0, 0)) depth ++;

        cout << depth << endl;
    }

    return 0;
}

dfs 560ms 时间O(n2^n) 空间O(n)
#include <iostream>
#include <algorithm>

using namespace std;

const int N = 55;

int n;
int q[N];
int up[N], down[N];
int ans;

void dfs(int u, int su, int sd) {
    if (su + sd >= ans) return; // ans不可能再小了

    if (u == n) {
        ans = su + sd;  // su, sd 分别表示 len(up[]), len(down[])
        return;
    }

    // 情况1:将当前数放到上升子序列中
    int k = 0;
    while (k < su && up[k] >= q[u]) k ++;
    int t = up[k];
    up[k] = q[u];
    if (k < su) dfs(u + 1, su, sd);
    else dfs(u + 1, su + 1, sd);
    up[k] = t;

    // 情况2:将当前数放到下降子序列中。
    k = 0;
    while (k < sd && down[k] <= q[u]) k ++;
    t = down[k];
    down[k] = q[u];
    if (k < sd) dfs(u + 1, su, sd);
    else dfs(u + 1, su, sd + 1);
    down[k] = t;
}

int main() {
    while (cin >> n, n) {
        for (int i = 0; i < n; i ++)
            cin >> q[i];

        ans = n;
        dfs(0, 0, 0);

        cout << ans << endl;
    }
}

#include <iostream>
#include <algorithm>
#include <cstring>

using namespace std;

const int N = 55;

int n;
int up[N], down[N], a[N];

bool dfs(int depth, int u, int su, int sd) {
    if (su + sd > depth) return false;
    if (u == n) return true; // u表示的是枚举每个顶点

    if (!su || up[su] >= a[u]) {
        up[su + 1] = a[u];
        if (dfs(depth, u + 1, su + 1, sd)) return true;
    } else {
        int l = 1, r = su;
        while (l < r) { // 坐标
            int mid = (l + r) >> 1;
            if (up[mid] < a[u]) r = mid;
            else l = mid + 1;
        }
        int t = up[l];
        up[l] = a[u];
        if (dfs(depth, u + 1, su, sd)) return true;
        up[l] = t;
    }

    if (!sd || down[sd] <= a[u]) {
        down[sd + 1] = a[u];
        if (dfs(depth, u + 1, su, sd + 1)) return true;
    } else {
        int l = 1, r = sd;
        while (l < r) {
            int mid = (l + r) >> 1;
            if (down[mid] > a[u]) r = mid;
            else l = mid + 1;
        }
        int t = down[l];
        down[l] = a[u];
        if (dfs(depth, u + 1, su, sd)) return true;
        down[l] = t;
    }

    return false;
}

int main() {
    while (cin >> n, n) {
        for (int i = 0; i < n; i ++) cin >> a[i];

        int depth = 0;

        while (!dfs(depth, 0, 0, 0)) depth ++; 
        cout << depth << endl;
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 这行代码的作用是将向量 `qDp` 的第一个元素复制到一个长度为 `t` 的向量 `qDp1` 中。具体来说,`length(t)` 表示向量 `t` 的长度,即向量 `qDp1` 的长度,`qDp(1)` 表示向量 `qDp` 的第一个元素,而 `ones(length(t),1)` 则表示一个元素全部为 1,长度为 `t` 的列向量。因此,`qDp(1)*ones(length(t),1)` 得到的就是一个元素全部为 `qDp` 的第一个元素,长度为 `t` 的列向量 `qDp1`。 ### 回答2: 在Matlab中,qDp1=qDp(1)*ones(length(t),1)的意思是将变量qDp中的第一个值与一个大小为t的向量相乘,并将结果赋值给变量qDp1。其中,qDp(1)表示变量qDp中的第一个值,而ones(length(t),1)则表示一个大小与向量t相同的全为1的列向量。 换言之,通过这条语句,我们将qDp的第一个值复制了t次,并将结果存储在变量qDp1中。这样做的目的可能是为了使qDp1的大小与t相同,方便后续的操作。 举个例子,假设我们有一个变量qDp=[5, 3, 7],而t是一个大小为10的向量。那么在执行qDp1=qDp(1)*ones(length(t),1)之后,变量qDp1会得到一个大小为10的列向量,其中所有的元素都是5。 总结来说,这条语句的作用是将变量qDp的第一个值复制多次,生成一个与t大小相同的列向量,并将结果保存在变量qDp1中。 ### 回答3: 在MATLAB中,"qDp(1)"表示矩阵或向量qDp的第一个元素。另一方面,"ones(length(t),1)"表示创建一个长度为t的矩阵或向量,其中所有元素的值都是1。所以,"qDp1=qDp(1)*ones(length(t),1);"这一行代码的作用是创建一个与t长度相同的向量qDp1,并且该向量的所有元素都等于qDp的第一个元素的值。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值