当前位置: 首页 > news >正文

动态规划,复习

一.动态规划

1.

思路:每次递增序列结束都取最优解

class Solution {
public:
    int findLengthOfLCIS(vector<int>& nums) {
        int ans = -1,temp = 1;
        for(int i = 0;i<nums.size()-1;i++){
            if(nums[i]<nums[i+1]) temp++;
            else{
                ans = max(ans,temp);
                temp = 1;
            }
        }
        ans = max(ans,temp);
        return ans;
    }
};

 2.

思路:动态规划五部曲

/*
dp[i]表示以i为结尾的最长子序列的长度
递推公式为前i项的哪个有最大子序列长度,哪个就是dp[i]=max(dp[i],dp[j]+1)
初始化为每个长度都为1;
前到后
*/

class Solution {
public:
    int lengthOfLIS(vector<int>& nums) {
        vector<int>dp(nums.size()+1,1);

        for(int i = 0;i<nums.size();i++){
            for(int j = 0;j<i;j++){
                if(nums[i]>nums[j])
                    dp[i] = max(dp[j]+1,dp[i]);
            }
        }
        return ranges::max(dp);
    }
};
 

 3./

思路:动规五部曲

/*
dp[i][j]表示为nums1前i-1项,和nums2前j-1项最大的重复子集dp[i][j];
dp[i][j] = dp[i-1][j-1]+1
初始化都为0
*/

class Solution {
public:
    int findLength(vector<int>& nums1, vector<int>& nums2) {
        vector<vector<int>> dp (nums1.size() + 1, vector<int>(nums2.size() + 1, 0));
        int result = 0;
        for (int i = 1; i <= nums1.size(); i++) {
            for (int j = 1; j <= nums2.size(); j++) {
                if (nums1[i - 1] == nums2[j - 1]) {
                    dp[i][j] = dp[i - 1][j - 1] + 1;
                }
                if (dp[i][j] > result) result = dp[i][j];
            }
        }
        return result;
    }
};

 4.

思路:动规五部曲

 

/*
dp[i][j]表示为text1前i-1项和text2的前j-1项的最大公共子序列长度
递推公式:dp[i][j] = dp[i-1][j-1]+1
初始化为0
*/

class Solution {
public:
    int longestCommonSubsequence(string text1, string text2) {
        vector<vector<int>>dp(text1.size()+1,vector<int>(text2.size()+1,0));
        
        for(int i = 1; i <= text1.size(); i++){
            for(int j = 1; j <= text2.size(); j++){
                if(text1[i-1]==text2[j-1])
                    dp[i][j] = dp[i-1][j-1]+1;
                else
                    dp[i][j] = max(dp[i-1][j],dp[i][j-1]);
            }
            
        }
        return dp[text1.size()][text2.size()];
    }
};

二.回顾

1. 埃拉托斯特尼筛法

#include <iostream>
#include <vector>
using namespace std;

const int MAX_N = 100000000; // n 的最大值为 10^8

// 埃拉托斯特尼筛法
void sieve_of_eratosthenes(int n, vector<int>& primes) {
    vector<bool> is_prime(n + 1, true); // 默认所有数是素数
    is_prime[0] = is_prime[1] = false;  // 0 和 1 不是素数

    for (int i = 2; i * i <= n; ++i) {
        if (is_prime[i]) {
            for (int j = i * i; j <= n; j += i) {
                is_prime[j] = false;
            }
        }
    }

    // 收集所有素数
    for (int i = 2; i <= n; ++i) {
        if (is_prime[i]) {
            primes.push_back(i);
        }
    }
}

int main() {
    ios::sync_with_stdio(0); // 加速 cin 和 cout
    
    int n, q;
    cin >> n >> q;

    // 找到小于等于 n 的所有素数
    vector<int> primes;
    sieve_of_eratosthenes(n, primes);

    // 处理每个查询
    while (q--) {
        int k;
        cin >> k;
        cout << primes[k - 1] << endl;  // 输出第 k 小的素数
    }

    return 0;
}

2.二分

思路:二分答案加贪心

class Solution {
public:
    int splitArray(vector<int>& nums, int k) {
        int l = 0,r= 0;
        for(int t:nums)
            r +=t;

        int ans = 0;
        while(l<=r){
            int mid = (r+l)>>1;
            if(check(nums,mid,k)){
                ans = mid;
                r = mid-1;
            }else
                l = mid+1;
        }
        return ans;
    }
    bool check(vector<int>& nums,int mid,int k){
        int sum = 0;
        int count = 1;
        for(int i = 0;i<nums.size();i++){
            if(nums[i]>mid)return false;
            sum+=nums[i];
            if(sum>mid){
                count++;
                sum = nums[i];
                if(count>k)return false;
            }
        }
        return true;
    }
};

3.二分 

思路:二分答案模板题

#include <stack>
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
#include <climits>
#include <cstdlib>
#include <cmath>
#include <unordered_set>
#include <unordered_map>
#include <map>
#include <set>
#include <cctype>
using namespace std;

const int MAXN = 50001;
int stone[MAXN], a, n, m;

bool check(int d) {
	int p = 0, ans = 0;
	for (int i = 1; i <= n; i++) {
		if (stone[i] - p < d) ans++;
		else p = stone[i];
	}
	if (ans <= m) return true;
	else return false;
}

int main() {
	scanf("%d %d %d", &a, &n, &m);
	for (int i = 1; i <= n; i++) scanf("%d", &stone[i]);
	stone[++n] = a;

	int l = 0, r = a, mid;
	while (l < r) {
		mid = (l + r + 1) / 2;
		if (check(mid)) l = mid;
		else r = mid - 1;
	}
	printf("%d\n", l);
	return 0;
}

4.卡特兰数

#include <stack>
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
#include <climits>
#include <cstdlib>
#include <cmath>
#include <unordered_set>
#include <unordered_map>
#include <map>
#include <set>
#include <cctype>

using namespace std;



int main() {
	int n;
	cin >> n;
	long long dp[10000];
	dp[0] = 1; dp[1] = 1;
	for (int i = 2; i <= 2 * n + 1; i++) {
		dp[i] = i * dp[i - 1];
	}
	
	cout << dp[2 * n] / (dp[n] * dp[n] * (n + 1));
	return 0;
}

 三.算阶

1.

思路:单调栈

#include <stack>
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
#include <climits>
#include <cstdlib>
#include <cmath>
#include <unordered_set>
#include <unordered_map>
#include <map>
#include <set>
#include <cctype>

using namespace std;


int main() {
	int n; 
	while (cin >> n && n != 0) {
		vector<long long>arr(n + 2,0);
		for (int i = 1; i <= n; i++)
			cin >> arr[i];

		long long stk[100005], top = 0;
		long long ans = INT_MIN;
		for (int i = 0; i <= n + 1; i++) {
			while (top && arr[stk[top]] > arr[i]) {
				int cur = stk[top--];
				int high = arr[cur];
				int weihgt = i - stk[top] - 1;
				ans = ans > high * weihgt ? ans : high * weihgt;
			}
			stk[++top] = i;
		}

		cout << ans << endl;
	}
	
	return 0;
}

 四.分治

1.

思路:归并排序的思想加上分治,先左边,在右边,在跨左右计算小和

#include <stack>
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
#include <climits>
#include <cstdlib>
#include <cmath>
#include <unordered_set>
#include <unordered_map>
#include <map>
#include <set>
#include <cctype>

using namespace std;


const int N = 100005;
long long arr[N], help[N];
int n;

long long merge(int l, int mid, int r) {
    long long sum = 0, ans = 0;
    for (int i = l, j = mid + 1, sum = 0; j <= r; j++) {
        while (arr[i] <= arr[j] && i <= mid) 
            sum += arr[i++];
        ans += sum;
    }

    int i = l;
    int a = l;
    int b = mid + 1;
    while (a <= mid && b <= r)
        help[i++] = arr[a] <= arr[b] ? arr[a++] : arr[b++];
    while (a <= mid)
        help[i++] = arr[a++];
    while (b <= r)
        help[i++] = arr[b++];
    for (int i = l; i <= r; i++)
        arr[i] = help[i];
    return ans;
}

long long small(int l, int r) {
    if (l == r)return 0;
    int mid = (l + r) / 2;
    return small(l, mid) + small(mid + 1, r) + merge(l, mid, r);

}

int main() {
    cin >> n;
    for (int i = 0; i < n; i++)
        cin >> arr[i];
    cout << small(0, n - 1);

    return 0;
}

 

相关文章:

  • 如何开发一个大模型应用?
  • php-fpm
  • Cloud之快照存储(Cloud Snapshot Storage)
  • 基于MATLAB的均匀面阵MUSIC算法DOA估计仿真
  • 2025年——自学黑客计划(网络安全)
  • 细说Java 引用(强、软、弱、虚)和 GC 流程(一)
  • DeepSeek集群版一键部署
  • PyQt 界面编程:QDialog、QWidget、QMainWindow 的面向过程与面向对象编程
  • 在Vue项目中使用three.js在前端页面展示PLY文件或STL文件
  • Python爬虫TLS
  • 玩转SpringCloud Stream
  • 【从0做项目】Java搜索引擎(7) web模块
  • 在做题中学习(90):螺旋矩阵II
  • ArcEngine开发中,当点击窗体中的ButtoncClick时,程序需等待五六秒才反应过来,的解决方案。
  • 深入理解 SQL 事务隔离级别:脏读、不可重复读和幻读
  • 技术速递|Copilot Edits(预览版)介绍
  • 春风席卷法(单词分泌物):一天记20个忘10个任务之3
  • Deepseek搭建本地知识库
  • sql注入漏洞
  • 已解决IDEA无法输入中文问题(亲测有效)
  • 菲律宾举行中期选举
  • 美国再工业化进程需要中国的产业支持
  • 碧桂园:砸锅卖铁保交房、持续推进保主体,尽快让公司恢复正常经营
  • 云南省安委会办公室:大理州安全生产形势比较严峻,事故总量一直居高不下
  • 中铁房地产24.7亿元竞得上海松江新城宅地,溢价率20.42%
  • 2025世界数字教育大会将于5月14日至16日在武汉举办