简单动态规划

来源:互联网 发布:奔驰数据库 编辑:程序博客网 时间:2024/05/21 10:01

 

动态规划问题必须同时具有如下二个要素:
最优子结构
  如果问题的一个最优解中包含了子问题的最优解,则该问题具有最优子结构。
动态规划以自底向上的方式来利用最优子结构
重叠子问题
  子问题的空间要“很小”,也就是用来解原问题的递归算法可反复的解同样的子问题,
而不是产生新的子问题。DP通过每个子问题只解一次,把解保存在一个需要时就可以查到的表中,
每次查表的时间为常数。

 

装配线调度


ans[i][j]表示从起点到装配置S(i,j)的最快可能时间
cost[i][j]表示在装配站S(i,j)的装配时间
trans[i][j]从装配下S(i,j)移到另一条装配线所花费的时间

状态方程:
ans[0][i] = cost[0][0] + cost[0][1]                    if 1 == i
ans[1][i] = cost[1][0] + cost[1][1]

ans[0][i] = min(ans[1][i-1]+trans[1][i-2]+cost[0][i],  if i >= 2
  ans[0][i-1]+cost[0][i])
ans[1][i] = min(ans[0][i-1]+trans[0][i-2]+cost[1][i],
  ans[1][i-1]+cost[1][i])


#include <iostream>
using std::cout;
using std::endl;

unsigned int cost[2][8] = {
                                {2, 7, 9, 3, 4, 8, 4, 3},
                                {4, 8, 5, 6, 4, 5, 7, 2}
                        };
unsigned int trans[2][5] = {
                                {2, 3, 1, 3, 4},
                                {2, 1, 2, 2, 1}
                        };

unsigned int ans[2][7] = { 0 };
unsigned int used[2][8] = { 0 };
unsigned int resTime = 0;
unsigned int resLine = 0;

void assembly()
{
        ans[0][1] = cost[0][0] + cost[0][1];
        ans[1][1] = cost[1][0] + cost[1][1];

        for (int i = 2; i <= 6; ++i)
        {
                if (ans[0][i-1] > (ans[1][i-1] + trans[1][i-2]))
                {
                        ans[0][i] = ans[1][i-1] + trans[1][i-2] + cost[0][i];
                        used[0][i] = 2;
                }
                else
                {
                        ans[0][i] = ans[0][i-1] + cost[0][i];
                        used[0][i] = 1;
                }

                if (ans[1][i-1] > (ans[0][i-1] + trans[0][i-2]))
                {
                        ans[1][i] = ans[0][i-1] + trans[0][i-2] + cost[1][i];
                        used[1][i] = 1;
                }
                else
                {
                        ans[1][i] = ans[1][i-1] + cost[1][i];
                        used[1][i] = 2;
                }
        }

        if ((ans[0][6] + cost[0][7]) > (ans[1][6] + cost[1][7]))
        {
                resTime = ans[1][6] + cost[1][7];
                resLine = 2;
        }
        else
        {
                resTime = ans[0][6] + cost[0][7];
                resLine = 1;
        }
}

void show()
{
        int tmp = resLine;
        cout << "minTime = " << resTime << endl;
        cout << "line = " << resLine << " ,station = 6"<< endl;
        for (int i = 6; i >= 2; --i)
        {
                cout << "line = " << used[tmp-1][i] << " ,station = " << i-1 << endl;
                tmp = used[tmp-1][i];
        }
}

int main()
{
        assembly();
        show();

        return 0;
}

矩阵链乘法
val[i][j]表示计算矩阵A(i,j)所需的标量乘法运算次数的最小值
状态方程
val[i][j] = 0                                      if i == j
            min(val[i][k]+val[k+1][j]+
  matrix[i-1]*matrix[k]*matrix[j])   if i < j && i >= k && k < j

#include <iostream>

using std::cout;
using std::endl;

int val[7][7] = { 0 };
int separate[7][7] = { 0 };

void matrix_chain_order()
{
        int matrix[7] = {30, 35, 15, 5, 10, 20, 25};
        int num = 6;
        for (int l = 2; l <= 6; ++l) // l is the chain length
                for (int i = 1; i <= num-l+1; ++i)
                {
                        int j = i+l-1;
                        val[i][j] =  0x0ffff;
                        for (int k = i; k <= j-1; ++k)
                        {
                                int tmp = val[i][k] + val[k+1][j] +
                                        matrix[i-1]*matrix[k]*matrix[j];
                                if (tmp < val[i][j])
                                {
                                        val[i][j] = tmp;
                                        separate[i][j] = k;
                                }
                        }
                }
}

void print_optimal_parents(int i, int j)
{
        if (i == j)
                cout << "A" << i;
        else
        {
                cout << "(";
                print_optimal_parents(i, separate[i][j]);
                print_optimal_parents(separate[i][j]+1, j);
                cout << ")";
        }
}

int main()
{
        matrix_chain_order();
        print_optimal_parents(1, 6);

        return 0;
}

最长公共子序列
给定两个序列 X = {x1, x2, ......, xm } 和 Y = {y1, y2, ......, yn },
找出 X 和 Y 的最长公共子序列。
一个给定序列的子序列是在该序列中删去若干个元素后得到的序列。
给定两个序列 X 和 Y ,当另一序列 Z 既是 X 的子序列又是 Y 的子序列时,
称 Z 是序列 X 和 Y 的公共子序列。
例如,若 X = {A, B, C, B, D, A, B },
             Y = {B, D, C, A, B, A },
序列{B, C, A }是 X 和 Y 的一个公共子序列,
序列{B, C, B, A }也是 X 和 Y 的一个公共子序列,且为最长公共子序列。


res[i][j]表示X的长度为i,Y的长度为j时,最长公共子序列大小
flag[i][j]表示X的长度为i,Y的长度为j时,X,Y移动的方向
-1: 仅X向后移动一位
0:  X与Y同时向后移动一位
1:  仅Y向后移动一位

状态方程
                  0                         if 0 ==i || 0 ==j   
res[i][j]= res[i-1][j-1]+1                  if X[i-1] == Y[j-1]
    max(res[i-1][j], res[i][j-1])    if X[i-1] != Y[j-1]


#include <iostream>
#include <string.h>
using std::cout;
using std::endl;

int res[100][100] = { 0 };
short flag[100][100] = { 0 };

void lcs_length(char str1[], int len1, char str2[], int len2)
{
        for (int i = 1; i <= len1; ++i)
                for (int j = 1; j <= len2; ++j)
                {
                        if (str1[i-1] == str2[j-1])
                        {
                                res[i][j] = res[i-1][j-1] + 1;
                                flag[i][j] = 0;
                        }
                        else
                        {
                                if (res[i-1][j] >= res[i][j-1])
                                {
                                        res[i][j] = res[i-1][j];
                                        flag[i][j] = -1;
                                }
                                else
                                {
                                        res[i][j] = res[i][j-1];
                                        flag[i][j] = 1;
                                }
                        }
                }
}

void lcs_print(char str1[], int i, int j)
{
        if (0 == i || 0 == j)
                return ;
        if (0 == flag[i][j])
        {
                lcs_print(str1, i-1, j-1);
                cout << str1[i-1];
        }
        else if (-1 == flag[i][j])
                lcs_print(str1, i-1, j);
        else
                lcs_print(str1, i, j-1);
}

int main()
{
        char str1[] = "ABCBDAB";
        char str2[] = "BDCABA";

        int len1 = strlen(str1);
        int len2 = strlen(str2);
        lcs_length(str1, len1, str2, len2);
        cout << "lcs = " << res[len1][len2] << endl;
        lcs_print(str1, len1, len2);
        cout << endl;
        return 0;
}

                                                              63,0-1        97%

原创粉丝点击