uva348 最优矩阵链乘 经典区间dp

// uva348 最优矩阵链乘
// 典型的区间dp
// dp[i][j] 表示矩阵i到j链乘所得到的最小花费
// dp[i][j] = min(dp[i][k]+dp[k+1][j]+a[i].pl*a[k].pr*a[j].pr);
// 在区间i到j上找一个k使得dp[i][k]+dp[k+1][j]这两部分的和在加上最后的
// a[i].pl*a[k].pr*p[i].pr的最小值;
// 能有这样的状态关键是; P =A[1] * A[2] * .... * A[K]
// 和 Q= A[K+1] * A[K+2] * .... * A[N] 这两部分的结果是不相互影响的,
// 因此只需要分别让 P 和 Q 最优方法计算,最优子结构!
// 边界时dp[i][i]=0;
//
// 这是一道痕经典的区间dp的题目,学会了用这种方法考虑问题
// 最后,还有就是递归打印,实在是十分奇妙。
// 还是挺高兴的呢。哎,继续练吧。。。。

#include <algorithm>
#include <bitset>
#include <cassert>
#include <cctype>
#include <cfloat>
#include <climits>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <deque>
#include <functional>
#include <iostream>
#include <list>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <stack>
#include <vector>
#define ceil(a,b) (((a)+(b)-1)/(b))
#define endl '\n'
#define gcd __gcd
#define highBit(x) (1ULL<<(63-__builtin_clzll(x)))
#define popCount __builtin_popcountll
typedef long long ll;
using namespace std;
const int MOD = 1000000007;
const long double PI = acos(-1.L);

template<class T> inline T lcm(const T& a, const T& b) { return a/gcd(a, b)*b; }
template<class T> inline T lowBit(const T& x) { return x&-x; }
template<class T> inline T maximize(T& a, const T& b) { return a=a<b?b:a; }
template<class T> inline T minimize(T& a, const T& b) { return a=a<b?a:b; }

const int maxn = 1008;
struct node {
	int pl;
	int pr;
}a[maxn];
ll d[maxn][maxn];
int path[maxn][maxn];
int n;
const ll inf = 0x4f4f4f4f4f4f4f4f;

ll dp(int i,int j){
	if (d[i][j]!=inf)
		return d[i][j];
	ll& ans = d[i][j];
	for (int k=i;k<j;k++){
		ll res = dp(i,k)+dp(k+1,j)+(ll)a[i].pl*a[k].pr*a[j].pr;
		if (ans>res){
			ans = res;
			path[i][j] = k;
		}
	}
	return ans;
}

void print(int i,int j){
	if (i==j){

		printf("A%d",i+1);
		return;
	}
	printf("(");
	for (int k=i;k<j;k++)
		if (path[i][j]==k){
			print(i,k);
			printf(" x ");
			print(k+1,j);
			break;
		}
	printf(")");
	//printf(")");
}

int main() {
	int kase = 0;
//	freopen("G:\\Code\\1.txt","r",stdin);
	while(scanf("%d",&n)!=EOF&&n){
		for (int i=0;i<n;i++)
			scanf("%d%d",&a[i].pl,&a[i].pr);
	//	memset(d,0x4f,sizeof(d));
	//	memset(path,0,sizeof(path));
		for (int i=0;i<n;i++)
			for (int j=0;j<n;j++){

				path[i][j]=0;
				d[i][j]=inf;
			}
		for (int i=0;i<n;i++)
			d[i][i]=0;
		dp(0,n-1);
		//printf("%lld\n",dp(0,n-1));
		printf("Case %d: ",++kase);
		print(0,n-1);
		puts("");
	}
	return 0;
}

时间: 2024-10-06 14:38:20

uva348 最优矩阵链乘 经典区间dp的相关文章

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

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

uva348Optimal Array Multiplication Sequence (最优矩阵链乘+路径输出)

Optimal Array Multiplication Sequence Time Limit:3000MS Memory Limit:0KB 64bit IO Format:%lld & %llu Submit Status Practice UVA 348 Appoint description: Description Download as PDF Given two arrays A and B, we can determine the array C = AB using the

dp-最优矩阵链乘

来自于紫书 题目大意 有\(n\)个矩阵组成的序列,设计一种运算顺序把它们依次乘起来,使得总运算量最小.假设第i个矩阵\(A_i\)是\(P_{i-1} \times P_i\)的.(\(n<=100\)) 例如:假设\(A\).\(B\).\(C\)分别是\(1 \times 50 , 50 \times 20 , 20 \times 5\) \(A \times (B \times C)\)的运算量为\(1 \times 50 \times 5 + (50 \times 20 \times

UVA 348 Optimal Array Multiplication Sequence(最优矩阵链乘)

L - Optimal Array Multiplication Sequence Time Limit:3000MS     Memory Limit:0KB     64bit IO Format:%lld & %llu Submit Status Practice UVA 348 Appoint description:  acmparand  (2013-08-02)System Crawler  (2015-08-04) Description Given two arrays A a

ZOJ3469 Food Delivery (经典区间dp)

本题和某一年的oi题非常相似,都是经典套路 我们知道我们在送完食物后既可以向前送也可以回头送,这就体现了区间dp的思想 为什么我们这次的区间dp不用枚举第三维k来枚举从哪里送过来呢? 因为送货员不是傻子,他如果送到你这了,那么在你们两之间的可以都顺路送了,所以我们只需要枚举两个位置就行 这题的输入不一定递增,所以建议输入完后排序 #include<iostream> #include<cstdio> #include<cstring> #include<algor

最优矩阵链乘

主要大区间化为小区间…… 先小区间求值…… 状态转移方程 f(i,j) = min{ f(i,k) + f(k+1,j) + p[i-1]p[k]p[j] }; poj 1651 http://poj.org/problem?id=1651 #include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include

1166 矩阵取数游戏[区间dp+高精度]

1166 矩阵取数游戏 2007年NOIP全国联赛提高组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 题解 题目描述 Description [问题描述]帅帅经常跟同学玩一个矩阵取数游戏:对于一个给定的n*m 的矩阵,矩阵中的每个元素aij均为非负整数.游戏规则如下:1. 每次取数时须从每行各取走一个元素,共n个.m次后取完矩阵所有元素:2. 每次取走的各个元素只能是该元素所在行的行首或行尾:3. 每次取数都有一个得分值,为每行取数的得分之和,每行取数的得分

石子合并问题,经典区间DP

一.直线型 问题描述: 有N堆石子排成一排,每堆石子有一定的数量.现要将N堆石子并成为一堆.合并的过程只能每次将相邻的两堆石子堆成一堆,每次合并花费的代价为这两堆石子的和,经过N-1次合并后成为一堆.求出总的代价最小值(或最大值). 思路: 设 DP[ i ][ j ] 表示第 i 堆合并到第 j 堆的代价的最小值(或最大值),然后,我们假设,sum[ i ] 为前 i 堆石子的总和,即前缀和.      然后就可以枚举区间长度,枚举中间点, 进行DP了, 复杂度o(n^3) dp[ i ][

poj 1390 Blocks (经典区间dp 方块消除)

Blocks Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 4250   Accepted: 1704 Description Some of you may have played a game called 'Blocks'. There are n blocks in a row, each box has a color. Here is an example: Gold, Silver, Silver, Sil