POJ 1651 Multiplication Puzzle 区间DP

题意:在一个数字序列中, 取出不包括头和尾的所有数字, 每次取出一个数字的代价等于取出的这个数和左右两个数的乘积, 求总代价和最小的取法

此小到大递归

 1 //#pragma comment(linker, "/STACK:167772160")//手动扩栈~~~~hdu 用c++交
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <cstdlib>
 5 #include <iostream>
 6 #include <queue>
 7 #include <stack>
 8 #include <cmath>
 9 #include <set>
10 #include <algorithm>
11 #include <vector>
12 // #include<malloc.h>
13 using namespace std;
14 #define clc(a,b) memset(a,b,sizeof(a))
15 #define LL long long
16 const int inf = 0x3f3f3f3f;
17 const double eps = 1e-5;
18 const double pi = acos(-1);
19 const LL mod = 1e9+7;
20 const int N = 710;
21 // inline int r(){
22 //     int x=0,f=1;char ch=getchar();
23 //     while(ch>‘9‘||ch<‘0‘){if(ch==‘-‘) f=-1;ch=getchar();}
24 //     while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();}
25 //     return x*f;
26 // }
27
28 int a[110],dp[110][110];//[i-1,j)的最小分数(i-1可以取,j取不到)
29 int main(){
30     int n;
31     while(~scanf("%d",&n)){
32         for(int i=1;i<=n;i++) scanf("%d",&a[i]);
33             clc(dp,0);
34          for(int len=2;len<n;len++){//枚举长度
35             for(int i=2;i+len<=n+1;i++){
36                 int j=i+len-1;
37                 dp[i][j]=inf;
38                 for(int k=i;k<j;k++){//枚举区间[i-1,j)中最后删除的值
39                     dp[i][j]=min(dp[i][j],dp[i][k]+dp[k+1][j]+a[i-1]*a[k]*a[j]);
40                 }
41             }
42         }
43         printf("%d\n",dp[2][n]);
44     }
45     return 0;
46 }
时间: 2024-12-21 12:21:07

POJ 1651 Multiplication Puzzle 区间DP的相关文章

POJ 1651 Multiplication Puzzle 区间dp(水

题目链接:点击打开链 题意: 给定一个数组,每次可以选择内部的一个数 i 消除,获得的价值就是 a[i-1] * a[i] * a[i+1] 问最小价值 思路: dp[l,r] = min( dp[l, i] + dp[i, r] + a[l] * a[i] * a[r]); #include <cstdio> #include <iostream> #include <algorithm> #include <queue> #include <cst

poj - 1651 - Multiplication Puzzle(dp)

题意:n个数(3 <= N <= 100)的序列,每次取一个数(不可以取最左最右)a[k],这时得到一个权值为a[k]左边的数 * a[k] * a[k]右边的数,问最小权值和. 题目链接:http://poj.org/problem?id=1651 -->>状态:dp[i][j]表示第i个数到第j个数组成的序列的最小权值和. 状态转移方程:dp[i][j] = min(dp[i][j], dp[i][k] + dp[k][j] + a[i] * a[k] * a[j]);(枚举最

POJ 1651 Multiplication Puzzle (区间dp)

题目大意:对n个数组成的序列取数,规定最两边不能取,每次取一个a[i],得到 a[l] * a[i] * a[r] 的分数(a[l]是a[i]左边的数,a[r]是a[i]右边的数),并把这个数从序列中移走,求n-2次取数后的得分和的最小值 分析:正着确定状态不好做,不如反着来,设dp[l][r]为向区间[l, r]中填满数所得到分数和的最小值,考虑最近一次填数的位置,不难得出: dp[l][r] = fmin(dp[l][m] + dp[m][r] + a[l] * a[m] * a[r]) (

POJ 1651 Multiplication Puzzle 题解 区间DP

题目链接:http://poj.org/problem?id=1651[题目描述]<乘法谜题>乘法谜题源自这样一个背景,我们有一行 n 张牌,平铺在桌面上,每张牌的牌面上都标有一个正整数.玩家的初始得分是 0,他接下来要进行 n-2 次操作,每次操作他都需要从桌面上取出一张牌,然后他的得分会加上他取出的这张牌与取出的这张牌的左边的牌以及取出的这张牌的右边的牌的乘积.在第 n-2 次操作结束后,桌面上将会只剩下两张牌.你的目的是帮助玩家决定取牌的顺序,使得玩家的最终得分最小.举个例子,如果一开始

POJ 1651 Multiplication Puzzle(区间dp)

Language: Default Multiplication Puzzle Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 6693   Accepted: 4083 Description The multiplication puzzle is played with a row of cards, each containing a single positive integer. During the move

POJ 1651 Multiplication Puzzle

区间DP.dp[i][j]表示(i,j)开区间内全部取走的最小值. #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> using namespace std; const int INF=0x7FFFFFFF; const int maxn=100+10; int a[maxn]; int dp[maxn][maxn]; int n; void init() { fo

POJ1651 Multiplication Puzzle 区间dp

题意:给一个序列,每次选一个数(记为b),计算左边离他最近的数(记为a),右边离他最近的数(记为c),计算a*b*c,sum+=a*b*c 重复操作直到剩下开头结尾两个数 不同的方案对应不同的sum 计算最小的sum值 分析:典型的区间dp,dp[i][j]表示把从i到j所有的数都选走得到的最小值 dp[i][j]=min(dp[i][j],dp[i][k-1]+dp[k+1][j]+num[k]*num[i-1]*num[j+1]): 注:记得预处理dp[i][i],i(2~n-1) #inc

poj 1651 Multiplication Puzzle【区间DP】

题目链接:http://poj.org/problem?id=1651 题意:初使ans=0,每次消去一个值,位置在pos(pos!=1 && pos !=n) 同时ans+=a[pos-1]*a[pos]*a[pos+1],一直消元素直到最后剩余2个,求方案最小的ans是多少? 代码: #include <stdio.h> #include <ctime> #include <math.h> #include <limits.h> #inc

POJ1651:Multiplication Puzzle(区间DP 最优矩阵链乘)

题意:除了头尾不能动,每次取出一个数字,这个数字与左右相邻数字的乘积为其价值,最后将所有价值加起来,要求最小值 和最优矩阵链乘模型一样,最后取出的数决定了序,如果没学过最优矩阵连乘找重复子问题还是比较难找的 DP //180K 0MS #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; int dp[110][110];