回文子序列
最长回文子序列是正序与逆序相同的非空字符串。例如,所有长度为1的字符串,civic,racecar,aibobphobia都是回文。设计算法,求给定输入字符串的最长回文子序列。例如,给定输入character,算法应该返回carac。算法的运行时间是怎么样的?
算法设计与分析:
注意这里是回文子序列,而不是回文子串。求子串和子序列有一些不同,这里的方法用于求子序列。
字串的意义是:aaabbb,需要连续的字符相同。
而子序列,是字母按照一定的排列顺序,保持回文的一致性就可以。
实现过程:将原字符串反转,然后用LCS_length(),Print_LCS()计算出最长公共子序列即可。
palidrome_longest.h
#include
#include
#include
using namespace std;
#define N 9 //输入您要判断的字符串的字符数
wchar_t b[N+1][N+1]={'S'}; //表示起点start
int c[N+1][N+1]={0};
wchar_t northwest=L'\\', up=L'|', leftway=L'-';
void LCS_length(char *x,char *y)
{
for(int i1=0;i1=c[i+1][j])
//c[i-1][j-1] 过渡到 c[i][j],需要将c[i-1][j]和c[i][j-1]比较大小
//取较大的那一个值
{
c[i+1][j+1]=c[i][j+1];
b[i+1][j+1]=up; //Up往上
}
else
{
c[i+1][j+1]=c[i+1][j];
b[i+1][j+1]=leftway; //Left往左
}
}
}
}
}
void Print_lcs(char *x,int i,int j)
{
if(i==0||j==0)
return;
if(b[i][j]==northwest)
{
Print_lcs(x,i-1,j-1);
cout<
palidrome_longest.cpp
#include "palidrome_longest.h"
int main()
{
char x[N+1]={0};
char y[N+1]={0};
char c;
cout<<"get the string you need to judge: "<>c;
y[i]=x[i]=c;
}
x[i]='\0';y[i]='\0';
cout<
实现结果
欧几里德旅行商问题
算法分析图
Eucilid_travel.h
#include
#include
using namespace std;
#define N 7 //确定有几个点?
struct travelnode
{
double x;
double y;
}T[N];
//计算两个点之间的直线距离
double distance(travelnode T[],int i,int j) //T[]的下标,第几个数?1,2....N
{
return sqrt((T[i].x-T[j].x)*(T[i].x-T[j].x)+(T[i].y-T[j].y)*(T[i].y-T[j].y));
}
double Bitonic_Eucilid(travelnode T[])
{
double b[N+1][N+1]={0};
//初始化b[1][4],注意初始下标从1开始,1,2.....N
b[1][5]=distance(T,1,2);
for(int j=3;j<=N;j++)
{
for(int i=1;ij-1)+(start->i)+length(j-1,j))
//即b[i][j]=b[i][j-1]+distance(T,j-1,j) 这里distance(T,j-1,j)封闭了路径
}
//注意:这里递归求解所得到的路径,b[i][j]不一定就是最短的欧几里德旅行商
//必须用min()维护旅行商信息
//用min()维护每一条线段[j-1,j],保证从length(start->j-1)+length(start->k)+length(k,j)均是最小的
//如图所示:对每一个线段[j-1,j]的两端进行维护,保证最短的Eucilid巡回,即维护b[j-1][j]
//在维护的过程中b[j-1][j]=min(b[k][j-1]+distance(k,j)),封闭了[k,j]就获取了最佳路径
//因为j是在最远端,1<=k<=j-1i+start->j的路径,但是巡路并不是封闭的
//最后确定b[j-1][j],即确定线段[j-1,j],完成巡路封闭。
//这里b[j-1][j]要保证遍历1<=kj-1)+(start->k)+length(k,j)
//由于1<=k
Eucilid_travel.cpp
#include "Eucilid_travel.h"
int main()
{
travelnode T[N+1]={0};
cout<<"Input the numbers in order : "<>T[i].x>>T[i].y;
}
cout<
旅行商的重构解
Print函数的递归分析
特别注意:
if(s
或者是:
if(s>k)
print_eucilid(solution,val,k);
如图中绿色线条所示:递归的过程,无论是s->val还是val->s,均是由较大坐标的点转向较小坐标的点。
二者的区别在于:s
而s>k的时候,则先递归输出顺时针方向其余的点,再输出val=solution[k] [s]的值。
注意这里是solution[k] [s]
当然递归和val的输出的先后顺序,取决于你是按顺时针还是逆时针输出。
Eucilid_travel_constitute.h
#include
#include
using namespace std;
#define N 7 //确定有几个点?
struct travelnode
{
double x;
double y;
}T[N];
//计算两个点之间的直线距离
double distance(travelnode T[],int i,int j) //T[]的下标,第几个数?1,2....N
{
return sqrt((T[i].x-T[j].x)*(T[i].x-T[j].x)+(T[i].y-T[j].y)*(T[i].y-T[j].y));
}
double Bitonic_Eucilid(travelnode T[],int solution[][N+1])
{
double b[N+1][N+1]={0};
//初始化b[1][8],注意初始下标从1开始,1,2.....N
b[1][9]=distance(T,1,2);
for(int j=3;j<=N;j++)
{
for(int i=1;ij-1)+(start->i)+length(j-1,j))
//即b[i][j]=b[i][j-1]+distance(T,j-1,j) 这里distance(T,j-1,j)封闭了路径
solution[i][j]=j-1;
}
//注意:这里递归求解所得到的路径,b[i][j]不一定就是最短的欧几里德旅行商
//必须用min()维护旅行商信息
//用min()维护每一条线段[j-1,j],保证从length(start->j-1)+length(start->k)+length(k,j)均是最小的
//如图所示:对每一个线段[j-1,j]的两端进行维护,保证最短的Eucilid巡回,即维护b[j-1][j]
//在维护的过程中b[j-1][j]=min(b[k][j-1]+distance(k,j)),封闭了[k,j]就获取了最佳路径
//因为j是在最远端,1<=k<=j-1i+start->j的路径,但是巡路并不是封闭的
//最后确定b[j-1][j],即确定线段[j-1,j],完成巡路封闭。
//这里b[j-1][j]要保证遍历1<=kj-1)+(start->k)+length(k,j)
//由于1<=k1)
print_eucilid(solution,s,val);
}
else
{
int val=solution[k][s];
if(val>1)
{
print_eucilid(solution,val,k);
}
cout<
Eucilid_travel_constitute.cpp
#include "Eucilid_travel_constitute.h"
int main()
{
travelnode T[N+1]={0};
int solution[N+1][N+1]={0};
cout<<"Input the numbers in order : "<>T[i].x>>T[i].y;
}
cout<
算法运行结果
][10]