递归结构中的DP

来源:互联网 发布:开淘宝用mac 编辑:程序博客网 时间:2024/06/06 07:33

1)表达式上的dp

问题:一个n*m矩阵由n行m列共n*m个数排列而成。两个矩阵A和B可以相乘当且仅当A的列数等于B的行数。一个N*M的矩阵乘以一个M*P的矩阵等于一个N*P的矩阵,运算量为nmp。
矩阵乘法满足结合律,A*B*C可以表示成(A*B)*C或者是A*(B*C),两者的运算量却不同。例如当A=2*3 B=3*4 C=4*5时,(A*B)*C=64而A*(B*C)=90。显然第一种顺序节省运算量。
现在给出N个矩阵,并输入N+1个数,第i个矩阵是a[i-1]*a[i]。

题目链接:http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=284

分析:跟区间dp一样,这个问题是在一个区间上进行动态规划的,假如我们要求 b-->e 区间上的最小值,我们找到一个中间区间 i ,让 b-->i 和 i -->e 的值最小,然后继续向下找

这是一个搜索的思想,可以用记忆话搜索降低复杂度。

其中的转移方程是 f【i】【j】 = f【i】【k】+f【k】【j】+ a [ i ] . x * a [ k ] . y * a [ j ] . y

如果不要求输出路径的话,可以用dp写,按照 j --  i 递增的顺序递推、

如果要求答应的路径的话,只能用记忆化搜索写,当然路径也是用递归写。

AC代码:

#include <cstdio>#include <cstring>using namespace std;const int N = 15;const int inf = 0x3f3f3f3f;struct Node{    int x,y;};Node a[N];int f[N][N],path[N][N];int dp(int b,int e){    if(b>=e)        return 0;    int& max=f[b][e];    if(max!=0)        return max;    max=inf;    for(int i=b; i<e; i++)    {        int tmp=dp(b,i)+dp(i+1,e)+a[b].x*a[i].y*a[e].y;  ///转移方程        if(tmp<max)        {            max=tmp;            path[b][e]=i;        }    }    return max;}int print(int b,int e){    if(b==e)        printf("A%d",b);    else    {        printf("(");        print(b,path[b][e]);        printf(" x ");        print(path[b][e]+1,e);        printf(")");    }}int main(){    int n,cas=1;    while(~scanf("%d",&n)&&n)    {        for(int i=1; i<=n; i++)            scanf("%d%d",&a[i].x,&a[i].y);        memset(f,0,sizeof(f));        memset(path,0,sizeof(path));        printf("Case %d: ",cas++);        dp(1,n);        print(1,n);        printf("\n");    }    return 0;}

2)凸多边形上的dp


0 0
原创粉丝点击