2022算法分析与练习十六

N皇后问题: 

题目描述

使用回溯法求解N后问题。

7eda9837c68a1136e8c10c7de323ddfe.png

输入

皇后的个数。

输出

每一种方案及总方案数。

样例输入 Copy

4

样例输出 Copy

0 1 0 0
0 0 0 2
3 0 0 0
0 0 4 0
----------------
0 0 1 0
2 0 0 0
0 0 0 3
0 4 0 0
----------------
总方案数为:2

本题详细题解

 0-1背包问题(回溯法)

题目描述

有n个物品,第i个物品重量为wi,价值为vi,现有一背包容量为C,要求把物品装入背包得到最大价值,并且要求出这些选取的物品。 要求用回溯法求解。

输入

多组测试数据,请处理到文件尾,一个整数表示物品的数量n,后一行有n个整数,代表价值,再后一行有n个整数,代表重量,最后有一个整数C代表背包容量,1<=n<=15,1<=vi<=30,1<=wi<=30,1<=C<=80。

输出

背包的最大总价值和所选取的物品,如果选取的方案有多种,请输出字典序最小的那种方案,每组测试数据应输出一行,在这里字典序最小的意思是,我们假设存在两种不同方案S,T所能得到的总价值相同且是最大的,对于方案S种选取|S|种物品,方案T选取|T|种物品,对于i=1,2...j-1,我们有si = ti,但sj < tj,则方案的S的字典序比方案T的字典序要小。由于没有使用special judge,所以如果选取得方案是S,请按照从小到大的顺序输出方案S中的物品下标。

样例输入 Copy

<span style="background-color:#ffffff"><span style="color:#333333"><span style="color:#333333"><span style="background-color:#f5f5f5">5
6 3 6 5 4
2 2 4 6 5
8</span></span></span></span>

样例输出 Copy

<span style="background-color:#ffffff"><span style="color:#333333"><span style="color:#333333"><span style="background-color:#f5f5f5">15 1 2 3</span></span></span></span>

 本题题解

 简单递归求和

题目描述

使用递归编写一个程序求如下表达式前n项的计算结果:  (n<=100)
1 -  3 + 5 - 7 + 9 - 11 +......
输入n,输出表达式的计算结果。

输入

多组输入,每组输入一个n,n<=100。

输出

输出表达式的计算结果。

样例输入 Copy

1
2

样例输出 Copy

1
-2
#include<math.h>
#include<stdio.h>
#include<algorithm>
#include<math.h>
#include<string.h>
#include<iostream>
# define  ll long long
using namespace std;
int a[105];
int main(){
	for(int i=1,cnt=1;cnt<=100;i+=2,cnt++){
		if(cnt%2==0)
		a[cnt]=a[cnt-1]-i;
		else a[cnt]=a[cnt-1]+i;
	}
	int n;
	while(cin>>n){
		cout<<a[n]<<endl;
	
	}
	
	return 0;
}

简单递归求和

题目描述

使用递归编写一个程序求如下表达式的计算结果:  (1<n<=20)
S(n) = 1*4 + 4*9 + 9*16 + 16*25 + ... + ((n-1)^2)*n^2
输入n,输出表达式S(n)的结果。

输入

单组输入,输入一个正整数n,1<n<=20。

输出

输出表达式S(n)的计算结果。

样例输入 Copy

3

样例输出 Copy

40

 就是简单递归,注意递归边界和s数组初始值的设置

#include<math.h>
#include<stdio.h>
#include<algorithm>
#include<math.h>
#include<string.h>
#include<iostream>
# define  ll long long
using namespace std;
int s[21];

int solve(int n){
	if(n<=1)return 0;
	if(n==2)return 4;
	else{
		return solve(n-1)+(n-1)*(n-1)*n*n;
	}
}
int main(){
	
	int n;
	cin>>n;
	cout<<solve(n);
	return 0;
}

递归求和

题目描述

X星人参加了一档幸运大抽奖节目,凭借无敌好运气中了一等奖。节目组给他准备了一个奖品箱,这个箱子中一共有M个格子,每个格子中只能放一个奖品。
现在一共有N个不同的奖品供X星人挑选,不同的奖品其价值不一定相等
“贪心的”X星人希望所挑选的奖品的价值和最大,需要你编写一个程序帮他计算出所能得到的最大价值和。

输入

单组输入。
第1行包含两个正整数M和N,分别表示奖品箱中格子的数量和奖品的总数。(1< M<=10^5且1<N<=10^5)
第2行包含N个正整数,分别表示N个奖品的价值,两两之间用空格隔开。

输出

奖品箱中所有奖品的最大价值和。

样例输入 Copy

3 5
1 3 2 6 5

样例输出 Copy

14

提交

 就是需要注意数值超过int范围,用Long long 就可以了

#include<math.h>
#include<stdio.h>
#include<algorithm>
#include<math.h>
#include<string.h>
# define  ll long long
using namespace std;

bool cmp(int x,int y){
return x>y;
}
int main(){
	int n,m;
	scanf("%d%d",&n,&m);
	int a[100004];
	for(int i=0;i<m;i++)scanf("%d",&a[i]);
	sort(a,a+m,cmp);
	ll sum=0;
	for(int i=0;i<n;i++)sum+=a[i];
	printf("%lld",sum);
	return 0;
}

文件存储

题目描述

如果有n个文件{F1,F2,F3,…,Fn}需要存放在大小为M的U盘中,文件i的大小为Si,1<=i<=n。请设计一个算法来提供一个存储方案,使得U盘中存储的文件数量最多。

输入

多组输入,对于每组测试数据,每1行的第1个数字表示U盘的容量M(以MB为单位,不超过256*1000MB),第2个数字表示待存储的文件个数n。
第2行表示待存储的n个文件的大小(以MB为单位)。

输出

输出最多可以存放的文件个数。

样例输入 Copy

10000 5
2000 1000 5000 3000 4000

样例输出 Copy

4
#include<math.h>
#include<stdio.h>
#include<algorithm>
#include<math.h>
#include<string.h>
#include<iostream>
# define  ll long long
using namespace std;
int a[1005];
int main(){
	int M,n;
	while(cin>>M>>n){
		memset(a,0,1005);
		for(int i=0;i<n;i++)cin>>a[i];
		sort(a,a+n);//就是选小的就行了
		int sum=0,cnt=0;
		while(sum<=M){
			sum+=a[cnt];
			cnt++;
		}
		cout<<cnt-1<<endl;
	} 
} 

 排列蛋卷

题目描述

刚考完研的TC同学这段时间在家闲得慌,因此他决定学点新手艺。今天他学习的内容是:做蛋卷。
由于是第一次做蛋卷,TC同学做出来蛋卷长短不一。看着这些长度都不一样的蛋卷,TC同学的强迫症又犯了。他希望能够拿出其中部分蛋卷,使得留下来的蛋卷能够按照长度从大到小的次序排列
请问他最少需要拿出多少根蛋卷

输入

单组输入,对于每一组测试数据,第1行N表示蛋卷的总数量(n<=1000)。 
第2行包含N个正整数,分别表示每一根蛋卷的长度。(单位:厘米) 
保证在同一组输入数据中每一根蛋卷的长度均不一样。

输出

输出最少需要拿出的蛋卷数量。

样例输入 Copy

5
15 18 17 11 12

样例输出 Copy

2

 思路很简单,因为是由大到小,我们上课学的是最长递增子序列,而这个是递减子序列,直接将这个数组反转就等于递减子序列了,通过一个vector来保存数据,如果大于vector最后一个放入的数则直接放入就可以了,如果小于则找到vector则找到vector中第一个大于a[i]的数并且将它替换  

#include<math.h>
#include<stdio.h>
#include<algorithm>
#include<math.h>
#include<string.h>
#include<iostream>
#include<vector>
# define  ll long long
using namespace std;
int a[1005];
int main(){
	int n;
	cin>>n;
	vector<int> ve;
	for(int i=0;i<n;i++)cin>>a[i];
	reverse(a,a+n);
	ve.push_back(a[0]);
	for(int i=1;i<n;i++){//
		if(a[i]>ve.back())ve.push_back(a[i]);
		else{
			*lower_bound(ve.begin(),ve.end(),a[i])=a[i];
		}
	}
	cout<<n-ve.size()<<endl;
} 

 X星人的基因

题目描述

X星人的基因由A、B、C、D、E五种不同的结构组合而成。
如果两个性别不同的X星人的基因序列相似度大于50%,按照X星的法律他们是禁止结婚的,等于50%据说还是可以的。
那么基因的相似度怎么计算呢?分别从两个人身上取长度均为N的基因片段,如果它们的最长公共子序列为M,则相似度=M/N。是不是很简单呢?
现在给你两段X星人的基因序列片段,请你判断他们是不是可以结婚?

输入

每一组测试数据包含3行,
第1行数字N表示待比较基因序列片段的长度,N<=10^3。
第2行和第3行为两个长度为N的基因序列片段。
输入0表示结束。

输出

两个X星人是否可以结婚,如果可以输出”Yes“,如果不可以输出”No“。

样例输入 Copy

8
A B C D E A B C
A C C D C B A E
6
A B C D E E
A E D C B B
0

样例输出 Copy

Yes
Yes

 思路:就是一个最长公共子序列问题,并且判断是否满足条件

#include<math.h>
#include<stdio.h>
#include<algorithm>
#include<math.h>
#include<string.h>
#include<iostream>
#include<vector>
# define  ll long long
using namespace std;
int lcs[1005][1005];
char a[1005],b[1005];
int main(){
	int n;
	string str1,str2;
	while(cin>>n&&n!=0){	
		for(int i=1;i<=n;i++)cin>>a[i];
		for(int i=1;i<=n;i++)cin>>b[i];
		for(int i=0;i<=n;i++){
		for(int j=0;j<=n;j++){
			if(i==0||j==0)lcs[i][j]=0;
			else{
				if(a[i]==b[j])lcs[i][j]=lcs[i-1][j-1]+1;
				else
				lcs[i][j]=max(lcs[i-1][j],lcs[i][j-1]);
			}
		}
	}
	if(lcs[n][n]*2<=n)cout<<"Yes"<<endl;
	else cout<<"No"<<endl;
	}
	return 0;
} 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

H-rosy

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

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

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

打赏作者

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

抵扣说明:

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

余额充值