POJ1651 D - Multiplication Puzzle (DP动态规划)

Description

The multiplication puzzle is played with a row of cards, each containing a single positive integer. During the move player takes one card out of the row and scores the number of points equal to the product of the number on the card taken and the numbers on the cards on the left and on the right of it. It is not allowed to take out the first and the last card in the row. After the final move, only two cards are left in the row. 

The goal is to take cards in such order as to minimize the total number of scored points. 

For example, if cards in the row contain numbers 10 1 50 20 5, player might take a card with 1, then 20 and 50, scoring 
10*1*50 + 50*20*5 + 10*50*5 = 500+5000+2500 = 8000

If he would take the cards in the opposite order, i.e. 50, then 20, then 1, the score would be 
1*50*20 + 1*20*5 + 10*1*5 = 1000+100+50 = 1150.

Input

The first line of the input contains the number of cards N (3 <= N <= 100). The second line contains N integers in the range from 1 to 100, separated by spaces.

Output

Output must contain a single integer - the minimal score.
 
题目解析:
给定一个数字数列,计算按某个规则所得的最小的值。
计算规则:从数字序列中依次取出一个值(不能是开头和结尾),每取出一个值,所对应的值是该数字和它两个相邻的数字乘积
 
思路:
采用动态规划递归的思想转换为子问题,dp[n][m]表示从第n个数到第m个数的所得的最小值。
譬如序列 10    1    50   50    20   5
           a[1] a[2] a[3] a[4] a[5] a[6]
dp[1][6] = min()
                dp[1][2]+dp[2][6]+a[1]*a[2]*a[6]
                dp[1][3]+dp[3][6]+a[1]*a[3]*a[6]
                dp[1][4]+dp[4][6]+a[1]*a[4]*a[6]
                dp[1][5]+dp[5][6]+a[1]*a[5]*a[6]
这四个中取一个最小值。
然后就再细分小问题,dp[2][6]  dp[3][6]  dp[4][6]等,不能直接计算的就再次细分。
只有两个数的话,初始化为0,譬如dp[1][2] dp[5][6]等
有三个数的话,就直接是三个数相乘。
所以递归的话用两层循环,外层循环表示每次计算的序列长度,内层循环表示对于外层的长度取到每个值。
 
代码如下:

#include <stdio.h>
#define MAX_CARDS 100
int cardArr[MAX_CARDS+1];

int dp[MAX_CARDS+1][MAX_CARDS+1] = {0}; //³¤¶È´Óiµ½j
int main()
{
      //freopen("input.txt","r",stdin);
      int cardNumber = 0;
      int i = 0;
      int j = 0;
      int k = 0;
      scanf("%d",&cardNumber);
      for(i=1;i<=cardNumber;i++)
      {
             scanf(" %d",&cardArr[i]);
      }
      for(i=1;i<cardNumber-1;i++)
      {
           dp[i][i+2] = cardArr[i] * cardArr[i+1] * cardArr[i+2];
      }

      for(i=4;i<=cardNumber;i++)   //序列的长度
     {
              for(j=1;j<=cardNumber-i+1;j++)
              {
                    int min = 0x7fffffff;
                    int temp;
                    for(k=j+1;k<j+i-1;k++)
                    {
                              temp = dp[j][k]+dp[k][j+i-1] + cardArr[j]*cardArr[k]*cardArr[j+i-1];
                              if(temp<min)
                              {
                                   dp[j][j+i-1] = temp;
                                   min = temp;
                              }

                     }

              }

       }
        printf("%d\n",dp[1][cardNumber]);
        return 0;
}

 

posted on 2015-12-03 14:10  挂在墙上的乌龟  阅读(221)  评论(0)    收藏  举报

导航