算法导论 动态规划

动态规划:dynamic programming

dp:

最优子结构

重叠子问题

独立子问题

步骤:

1.描述一个最优子结构

2.递归定义最优解

3.自底向上求出最优解的值

4.按要求求出一个最优解

 

其时间效率为:  有多少子问题*这些子问题分别有多少选择

总结:还挺好玩,感觉和高中的推理差不多,只是要深植于   找到特征+找到最优子结构+描述最优子结构+递归定义+求解+加上路径数组来构造最优解。

从前几项的关系得出推理:

从本问题可以被分为几个问题来得出推理

从要求的最后一项往前推

 

 

装配线调度:

 1 #include <iostream>
 2 #include <cstdio>
 3 
 4 using namespace std;
 5 
 6 int main()
 7 {
 8     int e1,e2,x1,x2,a1[7],a2[7];
 9     int f[2][7],fe,le,l[2][7],t1[7],t2[7];
10     scanf("%d%d",&e1,&e2);
11     scanf("%d%d",&x1,&x2);
12     for(int i=1;i<=6;i++)
13         scanf("%d",&a1[i]);
14     for(int i=1;i<=6;i++)
15         scanf("%d",&a2[i]);
16     for(int i=1;i<=5;i++)
17         scanf("%d",&t1[i]);
18     for(int i=1;i<=5;i++)
19         scanf("%d",&t2[i]);
20     f[1][1]=e1+a1[1];
21     f[2][1]=e2+a2[1];
22     
23     for(int j=2;j<=6;j++)
24     {
25         if(f[1][j-1]+a1[j]<=f[2][j-1]+t2[j-1]+a1[j])
26         {
27             f[1][j]=f[1][j-1]+a1[j];
28             l[1][j]=1;
29         }
30         else
31         {
32             f[1][j]=f[2][j-1]+t2[j-1]+a1[j];
33             l[1][j]=2;
34         }
35         
36         if(f[2][j-1]+a2[j]<=f[1][j-1]+t1[j-1]+a2[j])
37         {
38             f[2][j]=f[2][j-1]+a2[j];
39             l[2][j]=2;
40         }
41         else
42         {
43             f[2][j]=f[1][j-1]+t1[j-1]+a2[j];
44             l[2][j]=1;
45         }
46     }
47     if(f[1][6]+x1<=f[2][6]+x2)
48     {
49         fe=f[1][6]+x1;
50         le=1;
51     }
52     else
53     {
54         fe=f[2][6]+x2;
55         le=2;
56     }
57     
58     printf("%d\n",fe);
59     
60     int i=le;
61     printf("print line %d,station %d\n",i,6);
62     for(int j=6;j>=2;j--)
63     {
64         i=l[i][j];
65         printf("print line %d,station %d\n",i,j-1);
66     }
67     return 0;
68 }
源码实现

矩阵链乘法

节省了常数递归时间,还可以根据存取模式进行求解。

 1 #include <iostream>
 2 #include <cstdio>
 3 #define inf 1e9
 4 using namespace std;
 5 int s[7][7];
 6 void print_optimal_parens(int i,int j)
 7 {
 8     if(i==j)
 9         printf("A%d",i);
10     else
11     {
12         printf("(");
13         print_optimal_parens(i,s[i][j]);
14         print_optimal_parens(s[i][j]+1,j);
15         printf(")");
16     }
17         
18 }
19 
20 int main()
21 {
22     int p[7];
23     for(int i=0;i<=6;i++)
24         scanf("%d",&p[i]);
25     
26     int m[7][7];
27     for(int i=1;i<=6;i++)
28         m[i][i]=0;
29     for(int l=2;l<=6;l++)
30     {
31         for(int i=1;i<=6-l+1;i++)
32         {
33             int j=i+l-1;
34             m[i][j]=inf;
35             for(int k=i;k<=j-1;k++)
36             {
37                 int q=m[i][k]+m[k+1][j]+p[i-1]*p[k]*p[j];
38                 if(q<m[i][j])
39                 {
40                     m[i][j]=q;
41                     s[i][j]=k;
42                 }
43             }
44         }
45     }
46     printf("%d\n",m[1][6]);
47     
48     print_optimal_parens(1,6);
49     return 0;
50 }
View Code

 做备忘录的自顶向下的递归法时间效率O(n^3)

可以对一些子问题根本不需要求解的问题避免求解。

 1 #include <iostream>
 2 #include <cstdio>
 3 #define inf 1e9
 4 using namespace std;
 5 int s[7][7];
 6 int p[7];
 7 int m[7][7];
 8 void print_optimal_parens(int i,int j)
 9 {
10     if(i==j)
11         printf("A%d",i);
12     else
13     {
14         printf("(");
15         print_optimal_parens(i,s[i][j]);
16         print_optimal_parens(s[i][j]+1,j);
17         printf(")");
18     }
19         
20 }
21 
22 int lookup_chain(int i,int j)
23 {
24    if(m[i][j]<inf)
25        return m[i][j];
26     if(i==j)
27         m[i][j]=0;
28     for(int k=i;k<=j-1;k++)
29     {
30         int q=lookup_chain(i,k)+lookup_chain(k+1,j)+p[i-1]*p[k]*p[j];
31         if(q<m[i][j])
32         {
33             m[i][j]=q;
34             s[i][j]=k;
35         }
36     }
37     return m[i][j];
38 }
39 
40 void memorzed_matrix_chain()
41 {
42     for(int i=1;i<=6;i++)
43         for(int j=i;j<=6;j++)
44             m[i][j]=inf;
45     lookup_chain(1,6);
46 }
47 
48 
49 
50 
51 int main()
52 {
53     for(int i=0;i<=6;i++)
54         scanf("%d",&p[i]);
55     memorzed_matrix_chain();
56     printf("%d\n",m[1][6]);
57     
58     print_optimal_parens(1,6);
59     return 0;
60 }
View Code

 

 

最长公共子序列的实现算法:加打印最优解

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <string>
 5 
 6 using namespace std;
 7 
 8 void print_lcs(int b[][5],char x[],int i,int j)
 9 {
10     if(i==-1 || j==-1)
11         return;
12     if(b[i][j]==1)
13     {
14         printf("%c",x[i]);
15         print_lcs(b,x,i-1,j-1);
16     }
17     else if(b[i][j]==2)
18         print_lcs(b,x,i-1,j);
19     else if(b[i][j]==3)
20         print_lcs(b,x,i,j-1);
21     
22 }
23 int lcs(char x[],char y[])
24 {
25     int m=strlen(x);
26     int n=strlen(y);
27     int c[m+1][n+1];
28     int b[8][5];
29     for(int i=0;i<=m;i++)
30         c[i][0]=0;
31     for(int i=0;i<=n;i++)
32         c[0][i]=0;
33     
34     for(int i=0;i<m;i++)
35     {
36         for(int j=0;j<n;j++)
37         {
38             if(x[i]==y[j])
39             {
40                 c[i+1][j+1]=c[i][j]+1;
41                 b[i][j]=1;
42             }
43             
44             else if(c[i][j+1]>=c[i+1][j])
45             {
46                 c[i+1][j+1]=c[i][j+1];
47                 b[i][j]=2;
48             }
49             else if(c[i][j+1]<c[i+1][j])
50             {
51                 c[i+1][j+1]=c[i+1][j];
52                 b[i][j]=3;
53             }
54         }
55     }
56     print_lcs(b,x,m-1,n-1);
57     puts("");
58     return c[m][n];
59 }
60 int main()
61 {
62     char x[]="ABCBDAB";
63     char y[]="ABCB";
64     int LCS=lcs(x,y);
65     printf("%d\n",LCS);
66     return 0;
67 }
View Code

 

最优二叉搜索树

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <string>
 5 #define inf 0x3f3f3f3f
 6 using namespace std;
 7 
 8 
 9 float optimal_bst(float p[],float q[],int n)
10 {
11     float e[n+2][n+2],w[n+2][n+2];
12     int root[7][7];
13     
14     for(int i=1;i<=n+1;i++)
15     {
16         e[i][i-1]=q[i-1];
17         w[i][i-1]=q[i-1];
18     }
19     
20     for(int l=1;l<=n;l++)
21     {
22         for(int i=1;i<=n-l+1;i++)
23         {
24             int j=i+l-1;
25             e[i][j]=inf;
26             w[i][j]=w[i][j-1]+p[j]+q[j];
27             for(int r=i;r<=j;r++)
28             {
29                 float t=e[i][r-1]+e[r+1][j]+w[i][j];
30                 if(t<e[i][j])
31                 {
32                     e[i][j]=t;
33                     root[i][j]=r;
34                 }
35             }
36         }
37     }
38     return e[1][n];
39 }
40 
41 
42 int main()
43 {
44     float q[7],p[7];
45     for(int i=1;i<=5;i++)
46         scanf("%f",&p[i]);
47     for(int i=0;i<=5;i++)
48         scanf("%f",&q[i]);
49     printf("%f\n",optimal_bst(p,q,5));
50     return 0;
51 }
View Code

 

posted @ 2016-05-05 22:45  指尖泛出的繁华  阅读(220)  评论(0编辑  收藏  举报