c++寒假J312实战班错题集1.31

本文介绍了如何实现时间复杂度为O(nlogn)的最长递增子序列算法,以及如何解决ISBN号码识别和01背包问题的编程方法,通过动态规划进行解答。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

错题集

       1.Longest Ordered Subsequence(最长递增子序列)

        2.ISBN号码       

        3.开心的金明

Longest Ordered Subsequence(最长递增子序列)

这个题目的数据量不大,ʘ(n²)也过得了,但今天主要讲时间复杂度为ʘ(nlogn)的代码。

首先我们要设置一个vector<int> L{先赋字符串的第一个值} 
L[i]: 长度为i+1的LIS的最小结尾
在循环n-1次,每次判断,a比目前所有LIS结尾都大,直接附上去
否则就把下一个比他大的值,换成它的值,这样保证是递增的

看完了逻辑,再让我们看一下代码:

结合代码在来理解一下

#include <bits/stdc++.h>
using namespace std;
int main() {
  ios::sync_with_stdio(false), cin.tie(0);
  int N, a;
  cin >> N >> a;
  vector<int> L{a};  // L[i]: 长度为i+1的LIS的最小结尾
  for (int i = 1; i < N; i++) {
    cin >> a;
    if (a > L.back())  // a比目前所有LIS结尾都大,直接附上去
      L.push_back(a);
    else  // 1 3 4  8  9 + 7, 7替换8
      *lower_bound(begin(L), end(L), a) = a;
  }
  cout << L.size() << "\n";  // LIS长度

  return 0;
}

 ISBN号码  

这个题目比较好理解,但我做的时候犯了一个错,把判断识别码,看成了判断整个字符串。

我们直接来看一下标程:

#include<bits/stdc++.h>
using namespace std;
const int MOD=11;

int main(){
	string S;cin>>S;
	int sum=0,len=S.size();
	for(int i=0,j=1;i<len-1;i++){
		if(S[i]=='-')continue;	//分隔符就跳过 
		sum += (S[i]-'0')*j;	//计算正确的识别码 
		j++;
	} 
	sum %= MOD;
	//取出输入的识别码并转化为整数类型方便计算 
	int ans=S[len-1]=='X'?10:S[len-1]-'0';	
	if(ans==sum)cout<<"Right";	//匹配成功 
	else {
		//把原字符串的最后一位改为正确的识别码 
		S[len-1]=sum==10?'X':char(sum+'0');
		cout<<S;
	}
	return 0;
}

 开心的金明

这道题要重点讲一下,它是个典型的01背包,什么是01背包,就是在买时你可以选择买,或不买。所以我们来分析一下,每件物品只能购买一次,并且总价格不能超过N,可以把总价格看作背包容量,每件物品的的价格看作体积,v ,x ,j看作是价值。就好算的多了

这里就有两种解法:

1.定义F(i,j)为前i个物品,总体积不超过j的前提下,所能获得的最大价值,则显然有F(0,v)=0,并且有:F(i,v)=max(F(i−1,v),F(i−1,v−vi​)+vi​∗wi​)括号中第二部分要求v≥vi​,所求答案为 F(j,N)。

2.定义F(v)为体积不超过v的前提下所能获得的最大价值。则每次输入一个(vi​,wi​)之后,按照v从大到小的顺序,更新F(v)=max(F(v),F(v−vi​)+vi​wi​)即可,所求答案为F(N)。

我们来看一下代码:
 

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
int main() {
  ios::sync_with_stdio(false), cin.tie(0);
  int N, M;
  cin >> N >> M;
  vector<int> F(N + 1);
  for (int i = 0, v, p; i < M; i++) {
    cin >> v >> p;
    for (int j = N; j >= v; j--) F[j] = max(F[j], F[j - v] + v * p);
  }
  printf("%d\n", F[N]);
  return 0;
}
/* F(j,i), 总价i,[1,i]物品最大 价格*重要度为多少
   F(n,i) = max(F(n,i-1), F(n-V[i], i-1) + V[i]*P[i])
   i从小到大递推可以只保留v这个维度
*/

谢谢大家,欢迎点赞,收藏

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值