POJ 1651 Multiplication Puzzle(区间DP)

来源:互联网 发布:基地淘宝城 编辑:程序博客网 时间:2024/04/29 06:48

题目:Multiplication Puzzle

    题意: 
    n个正整数a1~an,将除a1和an的数依次取出 
    假设取出的是a[i],则score +=  a[i-1]*a[i]*a[i+1] 
    按不同顺序取出各数会得到不同的score, 
    求最小的score 
    分析: 
    状态 :  
    dp[i][j]表示将区间[i,j]内(不含a[i]、a[j])拿走的最小score 
    边界 : 
    if (i+1 >= j) return 0;//区间长度不足3 
    if (i+1==j-1) return a[i]*a[i+1]*a[j];//区间刚好3个数 
    状态转移: 
    考虑在区间[i,j]中最后拿走的数 (3种情况)  
    首先明确的是,要拿走的数是a[i+1]~a[j-1]  
    1.最后拿走a[i+1] :dp[i][j] = a[i]*a[i+1]*a[j] + dp[i+1][j]; 
    2.最后拿走a[j-1] :dp[i][j] = a[i]*a[j-1]*a[j] + dp[i][j-1]; 
    3.最后拿走a[k](i+1<k<j-1):dp[i][j] = a[i]*a[k]*a[j] + dp[i][k] + dp[k][j] 
    【将区间[i,k]和区间[k,j]全部拿完留下a[k]最后拿(因为在分成的两个区间中都是边界故没有被拿走)】 

#define mem(a,x) memset(a,x,sizeof(a))#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#define Sint(n) scanf("%d",&n)#define Sll(n) scanf("%I64d",&n)#define Schar(n) scanf("%c",&n)#define Sint2(x,y) scanf("%d %d",&x,&y)#define Sll2(x,y) scanf("%I64d %I64d",&x,&y)#define Pint(x) printf("%d",x)#define Pllc(x,c) printf("%I64d%c",x,c)#define Pintc(x,c) printf("%d%c",x,c)using namespace std;typedef long long ll;/*题意:n个正整数a1~an,将除a1和an的数依次取出假设取出的是a[i],则score +=  a[i-1]*a[i]*a[i+1]按不同顺序取出各数会得到不同的score,求最小的score分析:状态 : dp[i][j]表示将区间[i,j]内(不含a[i]、a[j])拿走的最小score边界 :if (i+1 >= j) return 0;//区间长度不足3if (i+1==j-1) return a[i]*a[i+1]*a[j];//区间刚好3个数状态转移:考虑在区间[i,j]中最后拿走的数 (3种情况) 首先明确的是,要拿走的数是a[i+1]~a[j-1] 1.最后拿走a[i+1] :dp[i][j] = a[i]*a[i+1]*a[j] + dp[i+1][j];2.最后拿走a[j-1] :dp[i][j] = a[i]*a[j-1]*a[j] + dp[i][j-1];3.最后拿走a[k](i+1<k<j-1):dp[i][j] = a[i]*a[k]*a[j] + dp[i][k] + dp[k][j]【将区间[i,k]和区间[k,j]全部拿完留下a[k]最后拿(因为在分成的两个区间中都是边界故没有被拿走)】 */const int N = 111;int dp[N][N];int a[N];int DP(int i,int j){if (i+1>=j) return 0;if (~dp[i][j]) return dp[i][j];if (i+1==j-1) return dp[i][j] = a[i]*a[i+1]*a[j]; // 第一种情况dp[i][j] = a[i]*a[i+1]*a[j] + DP(i+1,j);//第二种情况dp[i][j] = min(dp[i][j],a[i]*a[j-1]*a[j]+DP(i,j-1));//第三种情况for (int k = i+2;k < j-1;++k){dp[i][j] = min(dp[i][j],a[i]*a[k]*a[j]+DP(i,k)+DP(k,j));} return dp[i][j];} int main(){    mem(dp,-1);    int n;    while (Sint(n)==1)    {    for (int i = 1;i <= n;++i) Sint(a[i]);    Pintc(DP(1,n),'\n');}    return 0;}


0 0