算法1:动态规划

       动态规划的基本思想是:将求解的问题分解成若干个子问题,先求解子问题,然后再从这些子问题的解得到原问题的解。与分治法的区别是,适合用动态规划解决的问题,经分解得到的子问题往往不是相互独立的。动态规划将问题分解成子问题,但是子问题不相互独立,而是彼此依赖,相互提供帮助,很好的利用了子问题的结构信息。

动态规划的步骤是:

1.找出最优解的特征,并刻画其结构特征;

2.递归地定义最优值;

3.以自底向上的方式计算出最优值;

4.根据计算最优值的时得到的信息,构造最优解。

动态规划算法的有效性依赖于两个最重要的性质:最优子结构性质和重叠子问题性质。

栗子1,矩阵连乘问题。

 1 //动态规划——矩阵连乘问题
 2 #include<iostream>
 3 #include<cstring> 
 4 
 5 using namespace std;
 6 int p[7]={30,35,15,5,10,20,25};//6个矩阵
 7 int m[6][6];//存放计算量的矩阵
 8 int s[6][6];//存放分割点的矩阵
 9 
10 void matrixChain()//第三步:计算最优值(前面两步没法再代码中体现,是构思的过程)
11                   //生成断点矩阵的函数,计算出最优值,返回s矩阵
12 {
13     int length=6;
14     memset(m,0,sizeof(m));
15     memset(s,0,sizeof(s));
16     for(int r=2;r<=length;r++)//r表示的是计算的范围,开始只计算两个矩阵的计算量,然后依次计算3个,4个一直到目标的6个
17                               //这是动态规划自底向上的体现,从最小的单位开始计算
18     {
19         for(int i=1;i<=length-r+1;i++)//i,j分别表示当前所计算的范围
20         {
21             int j=i+r-1;
22             m[i][j]=m[i][i]+m[i+1][j]+p[i]*p[i-1]*p[j];//因为后面要求最优值,所以这里其实是随便求一个值
23             s[i][j]=i;
24             for(int k=i+1;k<j;k++)//范围内优化,找到最小的值
25             {
26                 int temp=m[i][k]+m[k+1][j]+p[i-1]*p[k]*p[j];
27                 if(temp<m[i][j])
28                 {
29                     m[i][j]=temp;
30                     s[i][j]=k;
31                 }
32             }
33         }
34     }
35 }
36 void TraceBack(int i,int j)//第4步:构造最优解。输入s矩阵和想要求解的范围,输出最佳的括号方案
37 {
38     if(i==j)
39     {
40         cout<<"M"<<"["<<i<<"]";
41         return;
42     }
43     cout<<"(";
44     TraceBack(i,s[i][j]);
45     TraceBack(s[i][j]+1,j);
46     cout<<")";
47 }
48 int main()
49 {
50     matrixChain();
51     TraceBack(1,6);
52     cout<<m[1][6]<<endl;
53     return 0;
54 }

 栗子2:最长公共子序列

 1 //动态规划-最长公共子序列
 2 #include<iostream>
 3 using namespace std;
 4 char x[8]={'Z','A','B','C','B','D','A','B'};//函数中根本不会计算x[0]和y[0],这两个位置的字母只是为了占坑用
 5 char y[7]={'Z','B','D','C','A','B','A'};
 6 int c[8][7]={0};//子序列的长度
 7 int b[8][7]={0};//子序列以哪种方式可以找到它最长子序列。递归方式
 8 //计算最优值
 9 void lcsLength()
10 {
11     int m=7;//第一个序列的长度
12     int n=6;//第二个序列的长度
13     for(int i=1;i<=m;i++)
14     {
15         for(int j=1;j<=n;j++)
16         {
17             if(x[i]==y[j])
18             {
19                 c[i][j]=c[i-1][j-1]+1;
20                 b[i][j]=1;
21             }
22             else
23             {
24                 if(c[i-1][j]>c[i][j-1])
25                 {
26                     c[i][j]=c[i-1][j];
27                     b[i][j]=2;
28                 }
29                 else
30                 {
31                     c[i][j]=c[i][j-1];
32                     b[i][j]=3;
33                 }
34                 
35             }
36             
37         }
38     }
39 }
40 //构造最优解
41 void lcs(int i,int j)//输出子序列和其长度
42 {
43     if(i==0||j==0)
44     return;
45     if(b[i][j]==1)
46     {
47         lcs(i-1,j-1);
48         cout<<x[i];
49     }
50     else
51     {
52         if(b[i][j]==2)
53         {
54             lcs(i-1,j);
55         }
56         else
57         {
58             lcs(i,j-1);
59         }
60         
61     }
62     
63  
64 
65 }
66 int main()
67 {
68     lcsLength();
69     lcs(7,6);
70     cout<<c[7][6]<<endl;//子序列的最大长度
71     return 0;
72 }

 在牛客上提交的版本,牛客只需要输出最长公共子序列的长度

 1 //动态规划-最长公共子序列
 2 #include<iostream>
 3 using namespace std;
 4 void lcsLength(char x[],char y[],int m,int n)
 5 {
 6     int c[m+1][n+1];//子序列的长度
 7     for(int i=0;i<m+1;i++)
 8     {
 9         for(int j=0;j<n+1;j++)
10             c[i][j]=0;
11     }
12     int b[m+1][n+1];//子序列以哪种方式可以找到它最长子序列。递归方式
13     for(int i=0;i<m+1;i++)
14     {
15         for(int j=0;j<n+1;j++)
16             b[i][j]=0;
17     }
18     for(int i=1;i<=m;i++)
19     {
20         for(int j=1;j<=n;j++)
21         {
22             if(x[i]==y[j])
23             {
24                 c[i][j]=c[i-1][j-1]+1;
25                 b[i][j]=1;
26             }
27             else
28             {
29                 if(c[i-1][j]>c[i][j-1])
30                 {
31                     c[i][j]=c[i-1][j];
32                     b[i][j]=2;
33                 }
34                 else
35                 {
36                     c[i][j]=c[i][j-1];
37                     b[i][j]=3;
38                 }
39                  
40             }
41              
42         }
43     }
44     cout<<c[m][n]<<endl;
45 }
46 void lcs()
47 {
48     char a[1024];
49     a[0]='Z';
50     char b[1024];
51     b[0]='Z';
52     string str1;
53      string str2;
54     while(cin>>str1>>str2)
55     {
56         for(int i=0;i<str1.size();i++)
57             a[i+1]=str1[i];
58         for(int i=0;i<str2.size();i++)
59             b[i+1]=str2[i];
60         lcsLength(a,b,str1.size(),str2.size());
61     }
62 }
63 int main()
64 {
65     lcs();
66     return 0;
67 }
原文地址:https://www.cnblogs.com/neverland0718/p/11348868.html