【算法设计与分析】期末编程复习题目

一些书上的例题。

矩阵链相乘问题

在这里插入图片描述
输入:

5
30 35 15 5 10 20

输出:

11875

代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e3+10;
int n,a[N];
int dp[N][N];//dp[i][j]表示从i-j的最小乘法次数 
int main()
{
	cin>>n;
	for(int i=0;i<=n;i++) cin>>a[i];//0 1是第1各 1 2是第2个 按后一个来看 
	memset(dp,0x3f,sizeof(dp));
	for(int i=0;i<=n;i++) dp[i][i]=0;
	//dp
	for(int k=2;k<=n;k++)//划分
	{
		for(int i=1;i<=n;i++)//表示第i个,同时也是两个参数中的第二个参数
		{
			int j=i+k-1;
			for(int t=i;t<j;t++)
			{
				dp[i][j]=min(dp[i][j],dp[i][t]+a[i-1]*a[t]*a[j]+dp[t+1][j]);
			}
		}
	} 
	cout<<dp[1][n];
	return 0;
}

最大子段和

在这里插入图片描述
输入:

6
-2 11 -4 13 -5 -2

输出:

20

O(n2):

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e4+10;
int n,a[N];
int ans=0;
int main()
{
	cin>>n;
	for(int i=1;i<=n;i++) cin>>a[i];
	for(int i=1;i<=n;i++)
	{
		int temp=0;
		for(int j=i;j<=n;j++)
		{
			temp+=a[j];
			ans=max(ans,temp);
		}
	}
	cout<<ans;
	return 0;
}

O(n):
用一个例子理解一下O(n):

比如有:-1 -2 -3 4 5 6 7 这一串数字
那么最大子段和肯定是从4-7的和,但我们是一层循环,从数字-1开始的。
我们这样计算:
-1 -2 -3 4 5 6 7
0  0  0  4 5 6 7
由于子段和小于0的按0处理,这样我们就相当于得到了从4-7的子段和。

代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e4+10;
int n,a[N];
int ans=0;
int dp[N];//dp[i]表示以i为结尾的最大子段和(要有a[i]的) 
int main()
{
	cin>>n;
	for(int i=1;i<=n;i++) cin>>a[i];
	int maxn=0;
	for(int i=1;i<=n;i++)
	{
		dp[i]=max(dp[i-1]+a[i],0);
		maxn=max(maxn,dp[i]);
	}
	cout<<maxn;
	return 0;
}

01背包dp版

在这里插入图片描述
输入:

5 10
2 6
2 3
6 5
5 4
4 6

输出:

15

代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e2+10;
int dp[N][1005];//dp[i][j]表示前i个物品,重量为j的最大价值 
int c,n;
int w[N],v[N];
int main()
{
	cin>>n>>c;
	for(int i=1;i<=n;i++)
	{
		cin>>w[i]>>v[i];
	}
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=c;j++)
		{
			if(j<w[i]) dp[i][j]=dp[i-1][j];//放不下了 
			else
			{
				dp[i][j]=max(dp[i-1][j-w[i]]+v[i],dp[i-1][j]);//拿和不拿 
			}
		}
	}
	cout<<dp[n][c];
	return 0;
}

会场安排问题

在这里插入图片描述
输入:

5
1 23
12 28
25 35
27 80
36 50 

输出:

3

代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+10;
int n;
int a[N],b[N];
int ans;
int main()
{
	cin>>n;
	for(int i=1;i<=n;i++) cin>>a[i]>>b[i];//开始和结束
	sort(a+1,a+1+n);
	sort(b+1,b+1+n);
	int j=1;
	for(int i=1;i<=n;i++)
	{
		if(a[i]>=b[j])//开始的在已有场次的后面可以沿用
		{
			j++;//结束时间就可以往后推 
		} 
		else 
		{
			ans++;
		}
	}
	cout<<ans;
	return 0;
}

ps:以下是我们学校OJ上的期末复习题。

二分搜索

在这里插入图片描述

一道模板二分题。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=110000+10;
int a[N];
int n;
int main()
{
	cin>>n;
	for(int i=1;i<=n;i++) cin>>a[i];
	int t;
	while(cin>>t)
	{
		if(!t) break;
		int l=1,r=n;
		int mid=(l+r)/2;
		int flag=0;
		while(l<r)
		{
			mid=(l+r)/2;
			if(a[mid]==t) 
			{
				flag=1;break;
			}
			else if(a[mid]<t)
			{
				l=mid+1;
			}
			else r=mid-1;
		}
		if(flag) cout<<"yes";
		else cout<<"no";
		cout<<endl;
	}
	return 0;
}

购书计划(贪心or直接模拟)

在这里插入图片描述
其他测试数据:

输入样例:
500 300 30 5
30 40 40 30 60

输出样例:
5

输入样例:
500 450 30 5
60 70 80 80 90

输出样例:
0

输入样例:
500 300 70 5
30 50 60 40 35

输出样例:
0
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e3+10;
//他打算把购买机票后剩下的钱都用来买书。
//小明也不打算买过于便宜的书。
int r,p,b,n;
int a[N];
int main()
{
	cin>>r>>p>>b>>n;
	for(int i=1;i<=n;i++)
	{
		cin>>a[i];
	}
	sort(a+1,a+1+n);
	int ans=0;int flag=0;
	for(int i=1;i<=n;i++)
	{
		if(a[i]>=b)
		{
			flag=i;break;
		}
	}
	r-=p;
	if(flag==0) 
	{
		ans=0;
		cout<<ans;
		return 0;
	}
	for(int i=flag;i<=n;i++)
	{
		if(r>=a[i])
		{
			r-=a[i];
			ans++;
		}
		else break;
	}
	cout<<ans;
	return 0;
}

带书计划(01背包+字典序)

在这里插入图片描述
Hint
《introduction_algorithm》《algorithm_training》和《data_struct》《beauty_of_math》两种组合都可以获得最大值,取字典序最小的按字典序输出。

注意:

  • 相同的重量要找字典序小的情况——对比字典序的时候可能出现拿的书的不同个数
  • 注意-1的特判

感觉写的有点复杂,不知道有没有更好的解法。
2022.1.6补充,有更好的解法:看这里
string可以直接字典序比较,用结构体排序+回溯法。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+10;
struct node
{
	string name;
	int zdx;
	int a;//weight
}a[105];
int n,m; 
string name[105];
int dp[105];
vector<int> v[N];//标记在当前价格下这本书是否带了:用字典序的编号 
int main()
{
	cin>>m>>n;
	for(int i=1;i<=n;i++)
	{
		cin>>a[i].name>>a[i].a;
		name[i]=a[i].name;
	}
	sort(name+1,name+1+n);
	//把字典序赋值 
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=n;j++)
		{
			if(a[i].name==name[j]) 
			{
				a[i].zdx=j;
				break;
			}
		}
	}
	dp[0]=0;
	for(int i=1;i<=n;i++)
	{
		for(int j=0;j<i;j++)
		{
			//要再拿 
			if(dp[j]+a[i].a<=m)
			{
				dp[i]=max(dp[i],dp[j]+a[i].a);
				if(v[dp[i]].empty())//之前没有
				{
					v[dp[i]]=v[dp[j]];
					v[dp[i]].push_back(a[i].zdx);
				}
				else
				{
					vector<int> temp;
					temp=v[dp[j]];
					temp.push_back(a[i].zdx);
					sort(v[dp[i]].begin(),v[dp[i]].end());
					sort(temp.begin(),temp.end());
					
					int flagg=0;//1表示现在的好 -1表示之前的好
					//注意 长度可能不一样 
					for(int k=0;k<min(temp.size(),v[dp[i]].size());k++)
					{
						if(temp[k]<v[dp[i]][k]) 
						{
							flagg=1;break;
						}
						else if(temp[k]>v[dp[i]][k])
						{
							flagg=-1;break;
						}
					} 
					if(flagg==1)
					{
						v[dp[i]]=temp;
					}
					
				 } 
			}
		}
		//cout<<dp[i]<<endl;
	}
	
	int maxn=-1;
	for(int i=1;i<=n;i++)
	{
		maxn=max(maxn,dp[i]);
	} 
	
	sort(v[maxn].begin(),v[maxn].end());
	for(auto x:v[maxn])
	{
		cout<<name[x]<<endl;
	}
	if(v[maxn].empty()) cout<<-1;
	return 0;
}
  • 0
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

karshey

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值