合工大程序设计艺术方法实验四动态规划Word格式.docx

上传人:b****6 文档编号:21787157 上传时间:2023-02-01 格式:DOCX 页数:14 大小:45.05KB
下载 相关 举报
合工大程序设计艺术方法实验四动态规划Word格式.docx_第1页
第1页 / 共14页
合工大程序设计艺术方法实验四动态规划Word格式.docx_第2页
第2页 / 共14页
合工大程序设计艺术方法实验四动态规划Word格式.docx_第3页
第3页 / 共14页
合工大程序设计艺术方法实验四动态规划Word格式.docx_第4页
第4页 / 共14页
合工大程序设计艺术方法实验四动态规划Word格式.docx_第5页
第5页 / 共14页
点击查看更多>>
下载资源
资源描述

合工大程序设计艺术方法实验四动态规划Word格式.docx

《合工大程序设计艺术方法实验四动态规划Word格式.docx》由会员分享,可在线阅读,更多相关《合工大程序设计艺术方法实验四动态规划Word格式.docx(14页珍藏版)》请在冰豆网上搜索。

合工大程序设计艺术方法实验四动态规划Word格式.docx

思考:

输出变换的步骤。

(3)输入一个矩阵,计算所有的子矩阵中和的最大值。

例如,输入

0-2-70

92-62

-41-41

-180-2

输出为:

15

四、实验结果与分析(源程序及相关说明)

1.求两个字符串的最长公共子序列

算法思想:

通过动态规划求解:

seat二维数组用于表示选择的最长公共子序列以及输出时选择的方向,其中0表示可选的子序列点,1表示递归选择str1(0,i-1),str2(0,j)的公共子序列,-1选择str1(0,i),str2(0,j-1)的公共子序列,Long表示选择str1(0,i),str2(0,j)的公共子序列的长度,其中当递归结束时,Long[m][n]就存储着最大的长度。

先将Long数组第一行第一列初始化为0,方便计算,接着如果str[i]==str[j],则seat[i][j]为可选点,seat[i][j]=0,同时Long[i][j]=Long[i-1][j-1]+1,如果str[i]!

=str[j],则Long[i][j]=max(Long[i-1][j]Long[i][j-1]),如果选择前者seat[i][j]=1,否则seat[i][j]=-1;

当循环遍历了两个字符串后,就得出结论,在根据seat中存储的元素值,从m,n开始(m,n分别为两字符串的长度),先递归,后输出对应位置在字符串中的字符,递归结束,就可以输出字符串。

 

#include"

stdafx.h"

#include<

stdio.h>

string>

iostream>

usingnamespacestd;

#defineMAXLEN100

intseat[MAXLEN][MAXLEN];

//其中0表示可选的子序列点,1表示选择str1(0,i-1),str2(0,j)的公共子序列,-1选择str1(0,i),str2(0,j-1)的公共子序列

intLong[MAXLEN][MAXLEN];

//表示选择str1(0,i),str2(0,j)的公共子序列的长度

voidLCSLength(stringstr1,stringstr2,intm,intn)

{

inti,j;

for(i=0;

i<

=m;

i++)

Long[i][0]=0;

for(j=1;

j<

=n;

j++)

Long[0][j]=0;

//第一行第一列不使用,方便计算

for(i=1;

{

for(j=1;

{

if(str1[i-1]==str2[j-1])

{

Long[i][j]=Long[i-1][j-1]+1;

seat[i][j]=0;

}

elseif(Long[i-1][j]>

=Long[i][j-1])

Long[i][j]=Long[i-1][j];

seat[i][j]=1;

else

Long[i][j]=Long[i][j-1];

seat[i][j]=-1;

}

}

}

//以str1为标准输出

boolPrint(stringstr1,inti,intj,int&

m,int&

n)

if(i==0||j==0)

returntrue;

if(seat[i][j]==0)

//先依次递归之后子序列,之后再输入该子序列符号,以保证输入的正确性

Print(str1,i-1,j-1,m,n);

m=i;

n=j;

cout<

<

str1[i-1];

elseif(seat[i][j]==1)

Print(str1,i-1,j,m,n);

else

Print(str1,i,j-1,m,n);

voidLCS()

stringstr1,str2;

intm=0,n=0,i=0,j=0;

cout<

"

输入第一个字符串:

"

<

endl;

cin>

>

str1;

输入第二个字符串:

str2;

i=str1.length();

j=str2.length();

LCSLength(str1,str2,i,j);

最长子序列为:

Print(str1,i,j,m,n);

最长子序列长度为:

Long[m][n]<

;

system("

pause"

);

int_tmain(intargc,_TCHAR*argv[])

LCS();

return0;

2.字符串的变换:

使用动态规划的思想:

定义两个数组,Distance表示距离,handle表示操作,其中handle存储的数1为删除,2为插入,3为替换,4为相同跳到下一个字符,5为结束状态。

先初始化,令handle开始的第一行第一列为5,如果str1[i]!

=str2[0],handle为3,列同理;

其中Distance为对应的行号或者列号。

两重for循环遍历所有组合的点,如果str1[i]==str2[j],则Distance[i][j]=Distance[i-1][j-1],handle[i][j]=4;

否则handle[i][j]=minval(Distance[i-1][j]+1,Distance[i][j-1]+1,Distance[i-1][j-1]+1,Distance[i][j]);

minval函数的作用是比较最大值,并返回最大值对应的操作,1为删除,2为插入,3为替换,当循环结束时,在Distance[m-1][n-1](m,n分别为两字符串的长度)中存储着最少操作次数

输出步骤:

最后先递归,后操作,修改str1字符串,表示操作的步骤。

#include<

vector>

#defineMAX1000

intDistance[MAX][MAX];

inthandle[MAX][MAX];

conststringOPERATOR_NAME[4]={

删除串a中的一个字符:

在串a插入一个元素:

将串a中的"

字母换为另一个字母:

};

//比较最大值,并返回最大值对应的操作,1为删除,2为插入,3为替换

intminval(intx,inty,intz,int&

d)

if(x<

y)

if(x<

z)

d=x;

return1;

else

d=z;

return3;

if(y<

d=y;

return2;

voidPrintHandle(inti,intj,string&

str1,stringstr2)

if(handle[i][j]==1)//删除

OPERATOR_NAME[0]<

str1[i]<

str1.erase(str1.begin()+i);

当前a字符串:

str1<

PrintHandle(i-1,j,str1,str2);

elseif(handle[i][j]==2)//插入

OPERATOR_NAME[1]<

str2[j]<

str1.insert(str1.begin()+i+1,str2[j]);

PrintHandle(i,j-1,str1,str2);

elseif(handle[i][j]==3)//替换

OPERATOR_NAME[2]<

OPERATOR_NAME[3]<

str1.insert(str1.begin()+i,str2[j]);

PrintHandle(i-1,j-1,str1,str2);

elseif(handle[i][j]==4)

elseif(handle[i][j]==5)

system("

if(str1.length()>

str2.length())

if(str1[i-1]!

=str2[j])

cout<

str1[i-1]<

str1.erase(str1.begin()+i-1);

if(i>

0)

PrintHandle(i-1,j,str1,str2);

if(str1[i]!

=str2[j-1])

str2[j-1]<

str1.insert(str1.begin()+i,str2[j-1]);

if(j>

PrintHandle(i,j-1,str1,str2);

//编辑距离函数,str1str2为操作的字符串

voidOUTdistance(stringstr1,stringstr2,intlenthofstr1,intlenthofstr2)

i<

lenthofstr1;

i++){

if(str1[i]==str2[0])

Distance[i][0]=i;

handle[i][0]=5;

Distance[i][0]=i+1;

handle[i][0]=3;

lenthofstr2;

if(str1[0]==str2[i])

Distance[0][i]=i;

handle[0][i]=5;

Distance[0][i]=i+1;

handle[0][i]=3;

j<

//如果对应的字符相等,原问题交给子问题处理,即不用任何操作

if(str1[i]==str2[j])

Distance[i][j]=Distance[i-1][j-1];

handle[i][j]=4;

//否则的话,对左、右、左上角的值进行求最小值

handle[i][j]=minval(Distance[i-1][j]+1,Distance[i][j-1]+1,Distance[i-1][j-1]+1,Distance[i][j]);

PrintHandle(lenthofstr1-1,lenthofstr2-1,str1,str2);

最少的操作次数是:

Distance[lenthofstr1-1][lenthofstr2-1]<

intSTRChang(){

intlenthofstr1=str1.length();

intlenthofstr2=str2.length();

OUTdistance(str1,str2,lenthofstr1,lenthofstr2);

STRChang();

3.计算所有的子矩阵中和的最大值

使用动态规划:

使用一个二维数组,其中num[i][j]存储矩阵i*j的元素和。

num存储的方法是:

num[i][j]+=num[i-1][j];

循环输入后就得到了矩阵元素和的二维数组。

使用三个变量i,j,k来遍历,一个矩阵大小是M*N的,那么使i从0到M,再使j从每一个i到M,遍历所有行可能。

再考虑列方向,直接在每一种i,j组合下,进行0到N的遍历,那么这样就等于是把所有子矩阵的情形给遍历完了。

每次遍历的过程是:

从i,j点开始,temp=num[j][k]-num[i-1][k],表示行为i-1到j,列为1到k的矩阵的值,nummax=max(nummax,0)+temp表示i-1到j,列为1到k的矩阵中从k向上最大的子矩阵元素和,Max=max(nummax,Max)表示最大的子矩阵和,当遍历结束,就可以求出最大举证和。

本算法可以求出100*100的矩阵

stdlib.h>

string.h>

time.h>

algorithm>

intnum[MAX][MAX];

voidsubMatrix()

intn;

intr,c;

inti,j,k;

srand(unsigned(time(0)));

请输入行列数:

r>

c;

memset(num,0,sizeof(num));

输入矩阵:

=r;

=c;

cin>

num[i][j];

num[i][j]+=num[i-1][j];

//num[i][j]表示i行j列矩阵的元素和

inttemp=0;

//记录一行的元素和

intMax=num[1][1];

intnummax;

//记录一个矩阵的元素和

for(j=i;

nummax=0;

for(k=1;

k<

k++)

temp=num[j][k]-num[i-1][k];

nummax=max(nummax,0)+temp;

Max=max(nummax,Max);

子矩阵中和的最大值为:

Max<

subMatrix();

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 成人教育 > 电大

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1