算法实验二题库二Word文档下载推荐.docx
《算法实验二题库二Word文档下载推荐.docx》由会员分享,可在线阅读,更多相关《算法实验二题库二Word文档下载推荐.docx(30页珍藏版)》请在冰豆网上搜索。
![算法实验二题库二Word文档下载推荐.docx](https://file1.bdocx.com/fileroot1/2022-11/29/fe42a87c-6b2f-477a-b210-284bc5aa23fc/fe42a87c-6b2f-477a-b210-284bc5aa23fc1.gif)
接下来每组数据两行,分别为待测的两组字符串。
每个字符串长度不大于1000.
由最长公共子序列问题的最优子结构性质可知,要找出X=<
x1,x2,…,xm>
和Y=<
y1,y2,…,yn>
的最长公共子序列,可按以下方式递归地进行:
当xm=yn时,找出Xm-1和Yn-1的最长公共子序列,然后在其尾部加上xm(=yn)即可得X和Y的一个最长公共子序列。
当xm≠yn时,必须解两个子问题,即找出Xm-1和Y的一个最长公共子序列及X和Yn-1的一个最长公共子序列。
这两个公共子序列中较长者即为X和Y的一个最长公共子序列。
由此递归结构容易看到最长公共子序列问题具有子问题重叠性质。
例如,在计算X和Y的最长公共子序列时,可能要计算出X和Yn-1及Xm-1和Y的最长公共子序列。
而这两个子问题都包含一个公共子问题,即计算Xm-1和Yn-1的最长公共子序列。
与矩阵连乘积最优计算次序问题类似,我们来建立子问题的最优值的递归关系。
用c[i,j]记录序列Xi和Yj的最长公共子序列的长度。
其中Xi=<
x1,x2,…,xi>
,Yj=<
y1,y2,…,yj>
。
当i=0或j=0时,空序列是Xi和Yj的最长公共子序列,故c[i,j]=0。
其他情况下,由定理可建立递归关系如下:
运行结果:
Question-4TheTriangle(动态规划)
7
38
810
2744
45265
在上图所示的三角形中,从顶部到底部,找一条路线,使得它的和最大。
当然,每一步只能走左下或者右下。
算法分析
利用动态规划的基本步骤来分析,首先找出最优解结构,l[i]表示1到i层路径的最优解,则l[i-1]亦为最优解(证明:
如果l[i-1]不为最优解,则1到i-1层有另外一条路径使得l[i-1]为最优解,这样就会致使l[i]路径不为最优解,矛盾)。
最优解结构:
这里用一位数组存储数字三角形。
Question-5超级台阶(动态规划)
有一楼梯共m级,刚开始时你在第一级,若每次只能跨上一级或二级,要走上第m级,共
有多少走法?
注:
规定从一级到一级有0种走法。
输入数据首先包含一个整数n(1<
=n<
=100),表示测试实例的个数,然后是n行数据,每行
包含一个整数m,(1<
=m<
=40),表示楼梯的级数。
输出
对于每个测试实例,请输出不同走法的数量。
(即有两个不同的楼梯,一个楼梯有2级,一个楼梯有3级)
只能说这题有一点DP的思想。
简单递归
Question-6最大和(动态规划)
给定一个由整数组成二维矩阵(r*c),现在需要找出它的一个子矩阵,使得这个子矩阵内的所有元素之和最大,并把这个子矩阵称为最大子矩阵。
例子:
0-2-70
92-62
-41-41
-180-2
其最大子矩阵为:
92
-41
-18
其元素总和为15。
第一行输入一个整数n(0<
n<
=100),表示有n组测试数据;
每组测试数据:
第一行有两个的整数r,c(0<
r,c<
=100),r、c分别代表矩阵的行和列;
随后有r行,每行有c个整数;
输出矩阵的最大子矩阵的元素之和。
用2维数组a[1:
m][1:
n]表示给定的m行n列的整数矩阵。
子数组a[i1
:
i2][j1
j2]表示左上角和右下角行列坐标分别为(i1,j1)和(i2,j2)的子矩阵,其各元素之和记为:
(1)
最大子矩阵和问题的最优解即为:
(2)
(3)
如果令:
(4)
那么式(4)就是我们熟悉的最大子序列和的问题。
根据以上分析我们可得到最大子矩阵和问题的算法:
Question-7剑客决斗(动态规划)
在路易十三和红衣主教黎塞留当权的时代,发生了一场决斗。
n个人站成一个圈,依次抽签。
抽中的人和他右边的人决斗,负者出圈。
这场决斗的最终结果关键取决于决斗的顺序。
现书籍任意两决斗中谁能胜出的信息,但“A赢了B”这种关系没有传递性。
例如,A比B强,B比C强,C比A强。
如果A和B先决斗,C最终会赢,但如果B和C决斗在先,则最后A会赢。
显然,他们三人中的第一场决斗直接影响最终结果。
假设现在n个人围成一个圈,按顺序编上编号1~n。
一共进行n-1场决斗。
第一场,其中一人(设i号)和他右边的人(即i+1号,若i=n,其右边人则为1号)。
负者被淘汰出圈外,由他旁边的人补上他的位置。
已知n个人之间的强弱关系(即任意两个人之间输赢关系)。
如果存在一种抽签方式使第k个人可能胜出,则我们说第k人有可能胜出,我们的任务是根据n个人的强弱关系,判断可能胜出的人数。
第一行是一个整数N(1<
=N<
=20)表示测试数据的组数。
第二行是一个整数n表示决斗的总人数。
(2<
=500)
随后的n行是一个n行n列的矩阵,矩阵中的第i行第j列如果为1表示第i个人与第j个人决斗时第i个人会胜出,为0则表示第i个人与第j个人决斗时第i个人会失败。
对于每组测试数据,输出可能胜出的人数,每组输出占一行。
动态规划(弗洛伊德),可以把一圈人从x分为两端都是x的一条线,x向中间打若最终x能遇到x则说明x可以取得胜利,中间得到meet[i][j]的转移方程有点像弗洛伊德算法,从中间找可以作为媒介的点,然后更新meet数组。
因为是在圈里所以要注意%操作。
Question-8最长上升子序列问题(动态规划)
有一个长为n的数列a0,a1,„„,an-1。
请求出这个序列中最长的上升子序列的长度。
上升子
序列指的是对于任意的i<
j都满足ai<
aj的子序列。
(1≤n≤1000,0≤ai≤1000000)。
第一行为n,下面一行为a0~an-1。
最长上升子序列的长度。
我们依次遍历整个序列,每一次求出从第一个数到当前这个数的最长上升子序列,直至遍历到最后一个数字为止,然后再取dp数组里最大的那个即为整个序列的最长上升子序列。
我们用dp[i]来存放序列1-i的最长上升子序列的长度,那么dp[i]=max(dp[j])+1,(j∈[1,i-1]);
显然dp[1]=1,我们从i=2开始遍历后面的元素即可。
Question-9独木舟上的旅行(贪婪法)
进行一次独木舟的旅行活动,独木舟可以在港口租到,并且之间没有区别。
一条独木舟最多
只能乘坐两个人,且乘客的总重量不能超过独木舟的最大承载量。
我们要尽量减少这次活动中的花销,所以要找出可以安置所有旅客的最少的独木舟条数。
现在请写一个程序,读入独木舟的最大承载量、旅客数目和每位旅客的重量。
根据给出的规则,计算要安置所有旅客必须的最少的独木舟条数,并输出结果。
第一行输入s,表示测试数据的组数;
每组数据的第一行包括两个整数w,n,80<
=w<
=200,1<
=300,w为一条独木舟的最大承载量,n为人数;
接下来的一组数据为每个人的重量(不能大于船的承载量)。
每组人数所需要的最少独木舟的条数。
先把各个人的体重排序,然后计算最重的人和最轻的人能否同乘一条舟,如果不能,则最重的人就要单独乘坐一条舟,再求最轻的和第二重的人的和,依次比较。
Question-10背包问题(贪心算法)
现在有很多物品(它们是可以分割的),我们知道它们每个物品的单位重量的价值v和重量w(1<
=v,w<
=10);
如果给你一个背包它能容纳的重量为m(10<
=20),你所要做的就是把物品装到背包里,使背包里的物品的价值总和最大。
第一行输入一个正整数n(1<
=5),表示有n组测试数据;
随后有n测试数据,每组测试数据的第一行有两个正整数s,m(1<
=s<
=10);
s表示有s个物品。
接下来的s行每行有两个正整数v,w。
输出每组测试数据中背包内的物品的价值和,每次输出占一行。
贪心原理,要求背包物品总价值最大,故尽可能多存放价值大的物品;
如图题目中给出的例子,背包可容纳重量15,故先放价值最大的A,将10斤A全部放入背包,然后放入价值次大的C,此时背包容纳量剩下15-10=5,而C还有9斤,因此剩下的全放C,总价值=(10*5)+(5*3)=65。
Question-11田忌赛马(动规中的贪心算法)
田忌赛马的故事大家应该都听过吧。
田忌经常与齐国众公子赛马,设重金赌注。
孙膑发
现他们的马脚力都差不多,马可分为上、中、下三等。
于是孙膑对田忌说:
“您只管下
大赌注,我能让您取胜。
”田忌相信并答应了他,与齐王和诸公子用千金来赌注。
比赛
即将开始,孙膑说:
“现在用您的下等马对付他们的上等马,拿您的上等马对付他们的
中等马,拿您的中等马对付他们的下等马。
”已经比了三场比赛,田忌一场败而两场胜,
最终赢得齐王的千金赌注。
现在题目的要求是这样的,给出田忌n匹马的速度,再给出
公子n匹马的速度,运用上述思想,求田忌最多能赢几场比赛。
我们规定,赢一场可
得200两黄金,输一场就扣200量黄金。
平局不得也不扣。
求田忌最多能赢多少黄金。
测试数据有多个。
每组测试数据的第一行是为n的正整数。
(1<
=1000),接下来的
两行为马的速度。
第一行为田忌的n匹马的速度,第二行为公子的n匹马的速度。
对于每一个测试用例,每行输出一个数,该数为田忌所能赢的最多的黄金数。
1如果田忌的慢马比齐王的慢马快,直接比赛。
赢的代价小!
2如果田忌的慢马比齐王的慢马慢,让他和齐王的快马比赛。
输的值!
3如果田忌的慢马的速度等于齐王的慢马1)如果田忌的快马比齐王的快马快,直接比赛。
赢!
2)如果田忌的慢马比齐王的快马慢,那让他和齐王最快的马比赛。
3)其他情况,直接退出。
统计比赛结果,算钱!
Question-12硬币问题(贪心算法)
有1元、5元、10元、50元、100元、500元的硬币各C1、C5、C10、C50、C100、C500枚。
现在要用这些硬币来支付A元、最少需要多少枚硬币?
假定本题至少存在一种支付方案。
第一行n为测试数据的组数。
以下各行依次为:
C1C5C10C50C100C500A
每行输出需要最少的硬币数
由贪心算法可知尽量用大面值的硬币组合来找钱,可以使使用的硬币最少。
而贪心算法对最少硬币问题的解决总是可以得到最优解很好的近似解。
本算法就是用贪心策略枚举出所有近似最优解,然后从中寻找到问题的最优解
寻找近似最优解群
(1)将硬币依面值大小排序
(2)按面值种类划分不同情况
有多少种面值就划分多少种情况.
每种情况的第一枚硬币面值各不一样,其后对剩余的硬币按面值从大到小排列。
源代码
Question-2
#include<
iostream>
usingnamespacestd;
#defineMAX100
//定义每组比赛成员的结构类型
typedefstructnode
{
intp1;
intp2;
}team;
teamX[MAX][MAX/2+1];
//X为解向量x[i][j]表示第i天第j场次现在赛的情况x[i][j].p1和x[i][j].p2
intnum,t[MAX];
//num表示比赛人数t[]分别表示每天比赛的场次数初始化为0
voidInit()
cout<
<
"
请输入运动员人数:
;
cin>
>
num;
for(inti=0;
i<
MAX;
i++)t[i]=0;
}
voidf(intfrom,intto,intday)//编号为from到to的n(n=to-from+1)个人从第day天开始比赛,全部安排下去的函数
intn=to-from+1,i,k;
if(n<
2)return;
if(n==2)//只有两人,直接在第day天安排比赛,比赛场次为++t[day]
{
X[day][++t[day]].p1=from;
X[day][t[day]].p2=to;
}
if(n>
2)//超过两人,才分成两组
intmid=from+n/2-1;
f(from,mid,day);
//组内比赛
f(mid+1,to,day);
//以下是组间比赛
for(k=0;
k<
=n/2;
k++)//在后n/2天内,分别与组2内队员(j+i+k)%(n/2)进行组间比赛
for(i=0;
i++)
X[n/2+k][++t[n/2+k]].p1=from+i;
X[n/2+k][t[n/2+k]].p2=(i+k)%(n/2+1)+mid+1;
}
voidOutput()
比赛安排如下:
\n"
for(inti=1;
=num;
第"
天:
endl;
for(intj=1;
j<
=t[i];
j++)
'
('
X[i][j].p1<
'
X[i][j].p2<
)'
'
intmain()
intz;
Init();
//初始化
f(1,num,1);
//从1到num个人从第一天开始调用函数
Output();
输入任意字符结束..."
z;
return0;
Question-3
#include<
cstring>
#defineN100
inta[N][N];
chars1[N],s2[N];
intmax(inta,intb)
returna>
=b?
a:
b;
intcount,i,j,length1,length2,z;
请输入需要测试几组数据:
count;
while(count--)
intcount=1;
cout<
请输入第"
count<
组待测序列:
s1+1>
s2+1;
length1=strlen(s1+1);
length2=strlen(s2+1);
=length1;
i++)
{
a[i][0]=0;
}
=length2;
a[0][i]=0;
for(i=1;
for(j=1;
if(s1[i]==s2[j])
a[i][j]=a[i-1][j-1]+1;
elsea[i][j]=max(a[i-1][j],a[i][j-1]);
最长公共子序列长度为:
a[length1][length2]<
endl<
count++;
Question-4
#defineN105
inta[N][N],dp[N][N],z;
intmain(){
intn,i,j,min;
输入行数:
while(cin>
n){
for(i=1;
=n;
for(j=1;
=i;
j++)
{
a[i][j];
dp[i][j]=0;
}
dp[1][1]=a[1][1];
for(i=2;
i++){
dp[i][1]=a[i][1]+dp[i-1][1];
for(j=2;
j++){
min=dp[i-1][j-1]>
dp[i-1][j]?
dp[i-1][j-1]:
dp[i-1][j];
dp[i][j]=a[i][j]+min;
}
intans=0;
if(ans<
dp[n][i])
ans=dp[n][i];
自上而下路径最大和为:
ans<
//最大和
Question-5
intmain()
{
intN;
cout<
请输入测试实例个数:
cin>
N;
__int64array[1024];
memset(array,0,1024);
请输入每个实例的楼梯级数:
while(N--)
intsum=0;
sum;
array[2]=1;
array[1]=1;
for(intindex=3;
index<
=sum;
index++)
array[index]=array[index-1]+array[index-2];
}
array[sum]<
system("
pause"
);
return0;
Question-6
stdio.h>
string.h>
string>
inta[102][102];
inti,j,k,m,r,c,max,temp,z,n;
请输入待测矩阵个数n:
n;
for(intcount=0;
count++)
输入第"
count+1<
个矩阵行数:
r;
个矩阵列数:
c;
=r;
{
for(j=0;
{
cin>
a[i][j]=a[i][j]+a[i-1][j];
for(i=1,m=a[1][0];
for(j=i;
for(k=max=0;
k++)
temp=a[j][k]-a[i-1][k];
max=(max>
=0?
max:
0)+temp;
m=max>
m?
m;
矩阵的最大和为:
m<
cin>
Question-7
stdlib.h>
intfight[501][501],meet[501][501],n;
//fight[i][j]:
i与jPK能否获胜,meet[i][j]:
i,j能否遇到
printf("
请输入测试数据的组数和决斗的总人数:
inti,j,k,m,t,cnt