美文网首页
动态规划之多边形游戏

动态规划之多边形游戏

作者: 碧影江白 | 来源:发表于2016-08-18 11:36 被阅读774次

    题目要求大致为已知如上数字符号,求按此计算的最大值和最小值
    思路如下:
    ①由于计算的过程当中,一定有一个运算符是多余的,所以哪一个运算符可以省去,因此,可以采用两个数组V[]与op[],来存放相应的数字与运算符。依次去掉一个运算符,每去掉一个就是一种新的情况,取这些情况的最大和最小值。
    ②在去掉一个运算符后,计算结果就是一个较长的式子,不同的运算先后情况会产生不同的结果,可以将不同的结果取最大值与最小值,来作为步骤①的一种情况。最小值为在最小值中取得最小值,最大值为在最大值中取得最大值。
    fmax=max{(max(f[num]))},fmin=min{(min(f[num]))}。
    ③接下来针对的是f[num]的具体解。在已知已经出现了一个待运算的式子以后,我们可以根据不同的运算符处理顺序将式子做出相应的运算(相当于在不同的位置添加不同数目的括号),已知在经过了一系列运算后,可以最终演变成两个数之间的运算,可能有两种情况,一种是两数相加,一种是相乘,进行相乘或者相加的两个数又是通过一系列运算得到的,也各自成一列式子,由不同的运算顺序得到。
    ④由此观之,这些运算应该是有两个数之间的递归算法得到,经过不同的划分,得到每一个式子的最大以及最小值,直到一个式子是由两个数字组成,为原始形象。
    ⑤由于全部存放是浪费空间的,由于在最终求解时只需要知道一种情况的最大和最小,那么,就可以根据两个数字之间的运算符,只保留每次运算后的最大和最小值两种情况。
    ⑥具体分析:在开始的时候由于封号两边的数字都直接由数字组成,不是由一段式子运算得到,所以最大和最小值都是本身,设两数字为a,b;数字之间符号为‘+‘,那么最大值为a+b,最小值也是a+b,数字之间符号为‘✲’么最大值为ab,最小值也是ab,在所以情况中找到最大值与最小值,假设符号左边的最大和最小为a,b,右边最大和最小为c,d。那么假设最后符号为+,那么最大和最小值应为max{a+c,a+d,b+c,b+d},min{a+c,a+d,b+c,b+d},如果符号为‘✲‘,那么那么最大和最小值应为max{ac,ad,bc,bd},min{ac,ad,bc,bd}。
    具体代码如下:
    #include <stdio.h>
    #include <stdlib.h>
    
    #define MAX_POINT 20
    int chain_value[MAX_POINT][MAX_POINT][2];  //chain[i][j][0]表示从v[i]节点开始,边长为j的链的最大值
                                               //chain[i][j][1]表示从v[i]节点开始,边长为j的链的最小值
    //从某个节点开始,即从该结点前开始分割,不同的分割方式。
    int n,*v;
    char *op;
    
    int get_max_sum();
    void chain_max(int start, int len, int k);
    void get_max_min(int a, int b, int c, int d, int start, int index, int len);
    
    int main()
    {
        int i;
        char ch;
    
        scanf("%d",&n);
        v = (int *)malloc(n*sizeof(int));
        op = (char *)malloc(n*sizeof(char));
    
        ch = getchar();                    //数据输入
        for (i = 0; i < n; i++)
        {
            scanf("%c",&op[i]);
            ch = getchar();
            scanf("%d",&v[i]);
            ch = getchar();
        }
    
        printf("MAX:%d\n",get_max_sum());   //得到最大值
    
        return 0;
    }//main
    
    
    int get_max_sum()
    {
        int i,k,start,max,tmp,len;
    
        for (i = 0; i < n; i++)
        {
            chain_value[i][0][0] = v[i];        //链长为0,即单个点的值
            chain_value[i][0][1] = v[i];        //以每个结点为起始结点进行判断,如果长度为,即不经过任何的运算,那么最大和最小的结果都是相同的,即原数本身。
        }
        
        for (len = 1; len < n; len++)  //控制链的长度,
        {           //n在前期手动输入,表示数字的个数||符号的个数||多边形的长度。
            for (start = 0; start < n ; start++)        //起点start配合链长,就可以得出除去某条边的效果
            {
                chain_value[start][len][0] = -9999;  
                chain_value[start][len][1] = 9999;
    //所有的结点最大设为-9999,最小为9999,用来进行大小比较时取得正确的最大最小值
                for (k = 0; k < len; k++)         //不同的操作符号的位置,k表示数学符号的下标
                {
                    chain_max(start,len,k);//取得最大*********************************************
                }
            }
        }
    
        max = chain_value[0][n-1][0];            //最终的最大值
        for (start = 1; start < n; start++)
        {
            tmp =  chain_value[start][n-1][0];
            max = max > tmp ? max : tmp;
        }
        return max;
    }
    
    void chain_max( int start, int len, int k)//start表示初始位置,len表链长,k为一个小于len的整数
    {
        int index,a,b,c,d;  //a<= m1 <= b  c<= m2 <=d
    //ab存放符号左边的最小值和最大值,cd存放符号右边的最小值和最大值。
    
        index = (start+k+1)%n;  //表示符号(op)或者符号后面的操作数的下标(不同的起始点之后的第k个字符(数字)),在接下来的运算中作为右边式子的起始位置
        
        a = chain_value[start][k][1];
        b = chain_value[start][k][0];    //从start到k的最大和最小值,即左边的最大和最小
        c = chain_value[index][len-k-1][1];
        d = chain_value[index][len-k-1][0];    //右边的最大和最小值
    //最开始时,a=b=chain_value[0][0][1];d=c= chain_value[1][0][1];当k增加
        
        get_max_min(a,b,c,d,start,index,len);   //根据符号的不同情况确定该段式子的最小和最大值。
    
    }
    
    void get_max_min(int a, int b, int c, int d, int start, int index, int len)
    {    
        int max_max,min_min,max_min,min_max;     
        int max,min;
    
        max = chain_value[start][len][0];        //先将max,min初始化
        min = chain_value[start][len][1];
    
        if ('+' == op[index])
        { 
            max = max > (b + d) ? max : (b + d); 
            min = min < (a + c) ? min : (a + c);    //如果为加,求得最大值和最小值
        }
        else if ('x' == op[index])//如果为乘,求得最大值和最小值
        {
            max_max = b * d;
            min_min = a * c;
            max_min = b * c;
            min_max = a * d;
                    
            max = max > max_max ? max :max_max;
            max = max > min_min ? max : min_min;
            max = max > max_min ? max : max_min;
            max = max > min_max ? max : min_max;
    
            min = min < max_max ? min :max_max;
            min = min < min_min ? min : min_min;
            min = min < max_min ? min : max_min;
            min = min < min_max ? min : min_max;
        }
    
        chain_value[start][len][0] = max;    //该最大值和最小值是在start到len的最大和最小值,将其正确赋值
        chain_value[start][len][1] = min;
    }
    

    相关文章

      网友评论

          本文标题:动态规划之多边形游戏

          本文链接:https://www.haomeiwen.com/subject/kadvsttx.html