1.数塔问题
完整代码:
#include<iostream>
#define n 5
using namespace std;
int DataTower(int d[n][n])
{
int maxAdd[n][n]={0},path[n][n]={0};
int i,j;
for(j=0;j<n;j++)
maxAdd[n-1][j]=d[n-1][j];
for(i=n-2;i>=0;i--)
{
for(j=0;j<=i;j++)
{
if(maxAdd[i+1][j]>maxAdd[i+1][j+1])
{
maxAdd[i][j]=d[i][j]+maxAdd[i+1][j];
path[i][j]=j;
}
else
{
maxAdd[i][j]=d[i][j]+maxAdd[i+1][j+1];
path[i][j]=j+1;
}
}
}
printf("路径为:%d", d[0][0]); //输出最顶层数字
j = path[0][0]; //顶层决策是选择下一层列下标为path[0][0]的元素
for (i = 1; i < n; i++)
{
printf("-->%d", d[i][j]);
j = path[i][j]; //本层决策是选择下一层列下标为path[i][j]的元素
}
printf("\n最大数值和为:");
return maxAdd[0][0]; //返回最大数值和,即最终的决策结果
}
int main()
{
int d[n][n]={{8},{12,15},{3,9,6},{8,10,5,12},{16,4,18,10,9}};
int max=DataTower(d);
cout<<max<<endl;
return 0;
}
运行结果:
2.图问题中的动态规划法
1>多段图的最短路径问题
完整代码:
#include<iostream>
using namespace std;
const int N = 20;
const int MAX=1000;
int arc[N][N];
int CreatGraph()
{
int i,j,k;
int weight;
int vnum,arcnum;
cout<<"请输入顶点和边的个数:"<<endl;
cin>>vnum>>arcnum;
for(i=0;i<vnum;i++)
{
for(j=0;j<vnum;j++)
{
arc[i][j]=MAX;
}
}
for(k=0;k<arcnum;k++)
{
cout<<"请输入边的两个顶点和权值"<<endl;
cin>>i>>j>>weight;
arc[i][j]=weight;
}
return vnum;
}
int BackPath(int n)
{
int i,j,temp;
int cost[N],path[N];
for(i=1;i<n;i++)
{
cost[i]=MAX;
path[i]=-1;
}
cost[0]=0;
path[0]=-1;
for(j=1;j<n;j++)
{
for(i=j-1;i>=0;i--)
{
if(arc[i][j]+cost[i]<cost[j])
{
cost[j]=arc[i][j]+cost[i];
path[j]=i;
}
}
}
cout<<n-1;
i=n-1;
while(path[i]>=0)
{
cout<<"<-"<<path[i];
i=path[i];
}
return cost[n-1];
}
int main()
{
int n=CreatGraph();
BackPath(n);
}
#include <iostream>
using namespace std;
const int MAX = 100;
const int n=3;//假设图中最多顶点个数
void Floyd(int arc[n][n],int dist[n][n])
{
int i,j,k;
for(i=0;i<n;i++)
{
for(j=0;j<n;j++)
{
dist[i][j]=arc[i][j];
}
}
for(i=0;i<n;i++)
{
for(j=0;j<n;j++)
{
for(k=0;k<n;k++)
{
if(dist[i][k]+dist[k][j]<dist[i][j])
{
dist[i][j]=dist[i][k]+dist[k][j];
}
}
}
}
}
int main()
{
int arc[n][n]={{0,4,11},{6,0,2},{3,MAX,0}};
int dist[n][n];
Floyd(arc,dist);
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
cout<<dist[i][j]<<" ";
cout<<endl;
}
return 0;
}
3.组合问题中的动态规划法
1>最长递增子序列问题
完整代码:
#include<iostream>
using namespace std;
int IncreaseOrder(int a[ ],int n)
{
int i,j,k,index;
int L[10],x[10][10];//L[i]表示元素序列a[0]-a[i]的最长递增子序列的长度,x[n][n]储存对应的最长递增子序列
for(i=0;i<n;i++)
{
L[i]=1;
x[i][0]=a[i];
}
for(i=1;i<n;i++)//依次计算a[0]-a[i]的最长递增子序列
{
int max=1;//初始化递增子序列长度的最大值
for(j=i-1;j>=0;j--)
{
if((a[j]<a[i])&&(max<L[j]+1))//maxL[0]+1,因此不执行if语句
{
max=L[j]+1;//前一个序列的最大子序列L[j]加1(a[i]的长度)
L[i]=max;//当前序列的最大子序列
for(k=0;k<max-1;k++)
{
x[i][k]=x[j][k];//将前一个最大子序列赋值给当前最大子序列(除最后一个元素)
}
x[i][max-1]=a[i];//当前最大子序列的最后一个元素是a[i]
}
}
}
for(index=0,i=1;i<n;i++)
{
if(L[index]<L[i])//遍历L[0]-L[n-1],与当前最大子序列长度比较,若大于当前最大子序列则替换index
index=i;
}
cout<<"最长公共子序列是:";
for(i=0;i<L[index];i++)
cout<<x[index][i]<<" ";
return L[index];
}
int main()
{
int a[]={5,2,8,6,3,6,9,7};
int len = IncreaseOrder(a, 8);
cout<<"最长递增子序列的长度是:"<<len<<endl;
return 0;
}
#include<iostream>
using namespace std;
int L[10][10],S[10][10];
int CommonOrder(char x[ ],int m,char y[ ],int n,char z[ ])
{
int i,j,k;
for(i=0;i<=m;i++)
L[i][0]=0;
for(j=0;j<=n;j++)
L[0][j]=0;
for(i=1;i<=m;i++)
{
for(j=1;j<=n;j++)
{
if(x[i-1]==y[j-1])
{
L[i][j]=L[i-1][j-1]+1;
S[i][j]=1;
}
else if(L[i][j-1]>L[i-1][j])
{
L[i][j]=L[i][j-1];
S[i][j]=2;
}
else
{
L[i][j]=L[i-1][j];
S[i][j]=3;
}
}
}
i=m;j=n;k=L[m][n];
while(i>0&&j>0)
{
if(S[i][j]==1)
{
z[k]=x[i-1];
k--;
i--;
j--;
}
else if(S[i][j]==2)
{
j--;
}
else
{
i--;
}
}
for(k=1;k<=L[m][n];k++)
cout<<z[k]<<" ";
return L[m][n];
}
int main()
{
char x[]={'a','b','c','b','d','b'};
char y[]={'a','c','b','b','a','b','d','b','b'};
char z[10];
cout<<"长度为:"<<CommonOrder(x,6,y,9,z)<<endl;
return 0;
}
#include <iostream>
using namespace std;
int V[6][11];
int x[5];
int KnapSack(int w[ ],int v[ ],int n,int C)
{
int i,j;
for(i=0;i<=n;i++)//将i个物品装入容量为0的背包
V[i][0]=0;
for(j=0;j<=C;j++)//将0个物品装入容量为i的背包
V[0][j]=0;
for(i=1;i<=n;i++)
{
for(j=1;j<=C;j++)
{
if(j<w[i-1])
V[i][j]=V[i-1][j];
else
{
if(V[i-1][j]>(V[i-1][j-w[i-1]]+v[i-1]))
V[i][j]=V[i-1][j];
else
V[i][j]=V[i-1][j-w[i-1]]+v[i-1];
}
}
}
for(j=C,i=n;i>0;i--)
{
if(V[i][j]>V[i-1][j])
{
x[i-1]=1;
j=j-w[i-1];
}
else
x[i-1]=0;
}
return V[n][C];
}
int main()
{
int w[]={2,2,6,5,4};
int v[]={6,3,5,4,6};
cout<<"背包获得的最大价值是:"<<KnapSack(w,v,5,10)<<endl;
cout<<"装入背包的物品是:";
for(int i=0;i<5;i++)
if (x[i] == 1) cout<<"物品"<<i+1<<" ";
cout<<endl;
return 0;
}
#include<iostream>
#include<iomanip>
#define N 5
using namespace std;
double C[N+1][N+1];
int R[N+1][N+1];
double OptimalBST(double p[ ], int n);
int main()
{
int i,j;
double p[]={0.1, 0.2, 0.4, 0.3};
cout<<OptimalBST(p,4)<<endl;
cout<<"矩阵C:"<<endl;
for(i=1;i<6;i++)
{
for(j=0;j<5;j++)
{
cout<<C[i][j]<<"\t";
}
cout<<endl;
}
cout<<endl;
cout<<"矩阵R:"<<endl;
for(i=1;i<6;i++)
{
for(j=0;j<5;j++)
{
cout<<R[i][j]<<"\t";
}
cout<<endl;
}
return 0;
}
double OptimalBST(double p[ ], int n)
{
int i, j, k, d, mink;
double min, sum;
for(i=1;i<=n;i++) //初始化主对角线和第一条次对角线
{
C[i][i-1] = 0;
C[i][i] = p[i-1]; R[i][i] = i;
}
C[n][n-1] = 0;
for(d=1;d<n;d++)
{ //按对角线逐条计算
for(i=1;i<=n-d;i++)
{
j=i+d;
min=1000; mink=i; sum=0; //假设1000为最大值
for(k=i;k<=j;k++)
{
sum=sum+p[k-1];
if(C[i][k-1]+C[k+1][j]<min)
{
min = C[i][k-1] + C[k+1][j];
mink = k;
}
}
C[i][j] = min + sum;
R[i][j] = mink;
}
}
return C[1][n];
}
#include<iostream>
#include<iomanip>
using namespace std;
int D[6][9];
int ASM(char P[ ], char T[ ], int m, int n);
int main()
{
char P[]="happy";
char T[]="hsppay";
cout<<"K-近似匹配求解过程:"<<endl;
cout<<ASM(P,T,5,6)<<endl;
return 0;
}
int min(int x,int y,int z)
{
int min;
if (x < y) min = x;
else min = y;
if (z < min)
min = z;
return min;
}
int ASM(char P[ ], char T[ ], int m, int n)
{
int i, j;
for (j = 1; j <= n; j++) //初始化第0行
D[0][j] = j;
for (i = 0; i <= m; i++) //初始化第0列
D[i][0] = i;
for (j = 1; j <= n; j++) //根据递推式依次计算每一列
{
for (i = 1; i <= m; i++)
{
if (P[i-1] == T[j-1])
D[i][j] =min(D[i-1][j-1], D[i-1][j]+1, D[i][j-1]+1);
else
D[i][j] = min(D[i-1][j-1]+1, D[i-1][j]+1, D[i][j-1]+1);
}
for (i = 1; i <= m; i++)
cout<<D[i][j]<<" ";
cout<<endl;
}
cout<<"最小差别数是:";
return D[m][n];
}