用动态规划法解决最长公共子序列问题.docx
《用动态规划法解决最长公共子序列问题.docx》由会员分享,可在线阅读,更多相关《用动态规划法解决最长公共子序列问题.docx(7页珍藏版)》请在冰豆网上搜索。
![用动态规划法解决最长公共子序列问题.docx](https://file1.bdocx.com/fileroot1/2023-3/31/f352ee37-6fda-43af-9c96-928c9e0af56e/f352ee37-6fda-43af-9c96-928c9e0af56e1.gif)
用动态规划法解决最长公共子序列问题
用动态规划法解决最长公共子序列问题
动态规划解最长子序列
一、课程设计目的
掌握动态规划法的原理,并能够按其原理编程实现求两个序列数据的最长公共子系列,以加深对其的理解。
二、课程设计内容
1、用动态规划法解决最长子序列问题
2、交互输入两个序列数据
3、输出两个序列的最长公共子序列
三、概要设计
四、详细设计与实现
#include"iostream.h"
#include"iomanip.h"
#definemax100
voidLCSLength(intm,intn,char*x,char*y,char*b)
{
inti,j,k;
intc[max][max];
for(i=1;i<=m;i++)
{
c[i][0]=0;
}
for(i=1;i<=n;i++)
{
c[0][i]=0;
}
for(i=1;i<=m;i++)
{
for(j=1;j<=n;j++)
{
if(x[i-1]==y[j-1])
{
c[i][j]=c[i-1][j-1]+1;
k=i*(n+1)+j;
b[k]='\\';
}
elseif(c[i-1][j]>=c[i][j-1])
{
c[i][j]=c[i-1][j];
k=i*(n+1)+j;
b[k]='|';
}
else{
c[i][j]=c[i][j-1];
k=i*(n+1)+j;
b[k]='-';
}
}
}
}
voidLCS(inti,intj,char*x,char*b,intwidth)
{
if(i==0||j==0)
return;
intk=i*(width+1)+j;
if(b[k]=='\\'){
LCS(i-1,j-1,x,b,width);
cout<}
elseif(b[k]=='|')
{
LCS(i-1,j,x,b,width);
}
else
{
LCS(i,j-1,x,b,width);
}
}
voidmain()
{
charx[max]={'a','b','c','b','d','a','b'};
chary[max]={'b','d','c','a','b','a'};
intm=7;
intn=6;
charb[max]={0};
LCSLength(m,n,x,y,b);
LCS(m,n,x,b,n);
cout<}
最长公共子序列问题具有最优子结构性质
设
X = { x1 , ... , xm }
Y = { y1 , ... , yn }
及它们的最长子序列
Z = { z1 , ... , zk }
则
1、若 xm = yn , 则 zk = xm = yn,且Z[k-1] 是 X[m-1] 和 Y[n-1] 的最长公共子序列
2、若 xm !
= yn ,且 zk !
= xm , 则 Z 是 X[m-1] 和 Y 的最长公共子序列
3、若 xm !
= yn , 且 zk !
= yn , 则 Z 是 Y[n-1] 和 X 的最长公共子序列
由性质导出子问题的递归结构
当 i = 0 , j = 0 时 , c[i][j] = 0
当 i , j > 0 ; xi = yi 时 , c[i][j] = c[i-1][j-1] + 1
当 i , j > 0 ; xi !
= yi 时 , c[i][j] = max { c[i][j-1] , c[i-1][j] }
#include
#definemax(a,b)a>b?
a:
b
#defineM100
voiddisplay(int&n,int&C,intw[M],intv[M])
{
inti;
cout<<"请输入物品种数n:
";
cin>>n;
cout<cout<<"请输入背包总容量C:
";
cin>>C;
cout<cout<<"请输入各物品的大小或重量w:
"<w[0]=0;
for(i=1;i<=n;i++)
cin>>w[i];
cout<<"请输入各物品其价值v:
"<v[0]=0;
for(i=1;i<=n;i++)
cin>>v[i];
};
intknapsack(int&n,int&C,intw[M],intv[M],intV[M][M])
{
inti,j;
for(i=0;i<=n;i++)
for(j=0;j<=C;j++)
{
if(i==0||j==0)
V[i][j]=0;
elseif(w[i]>j)
V[i][j]=V[i-1][j];
elseif(w[i]<=j)
V[i][j]=max(V[i-1][j],V[i-1][j-w[i]]+v[i]);
}
returnV[n][C];
};
voidtraceback(intn,intC,intw[M],intx[M],intV[M][M])
{
for(inti=1;i<=n;i++)
{
if(V[i][C]==V[i-1][C])
x[i]=0;
else
{
x[i]=1;
C=C-w[i];
}
}
//x[n]=(V[n][C]>0)?
1:
0;
};
voidmain()
{
inti,j,n,C;
charch;
intw[M],v[M],x[M];
intV[M][M];
while
(1)
{
display(n,C,w,v);
cout<<"运算结果如下:
"<for(i=1;i<=n;i++)
x[i]=0;
knapsack(n,C,w,v,V);
cout<<"";
for(j=0;j<=C;j++)
cout<cout<for(i=0;i<=n;i++)
{
cout<
for(j=0;j<=C;j++)
{
cout<}
cout<cout<}
cout<<"选择的物向量表示为:
";
cout<<"(";
traceback(n,C,w,x,V);
for(i=1;i<=n;i++)
cout<cout<<")"<cout<<"背包最大价值为:
"<cout<cout<<"按Y或y继续操作,否则按任意键"<cin>>ch;
if(ch=='Y'||ch=='y')
continue;
else
break;
}
}