区间dp -- Multiplication Puzzle POJ - 1651

Multiplication Puzzle POJ - 1651

题意:
给你 n(2 < n <= 100)个数,求把这n个数删到只剩首尾两个数的代价和,删掉一个数的代价是这个数和与它相邻左右两个数的乘积。

例如:
如果有6个数10 、1、50 、20、 5,删数的顺序为 1、20、50,则代价和为:
10 * 1 * 50 + 50 * 20 * 5 + 10 * 50 * 5 = 500 + 5000 + 2500 = 8000。

如果删数的顺序为 50、20、1,则代价和为:
1 * 50 * 20 + 1 * 20 * 5 + 10 * 1 * 5 = 1000 + 100 + 50 = 1150。

思路:

  • 此题为常规区间dp,先把n个数划分为基本区间(显然基本区间的长度为3),在由基本区间逐步扩大到整个区间 [0, n - 1]。

  • dp[i][j]表示删掉区间 [i, j] 间的数的最小代价。

  • 先把dp[i][j]置为无穷大,再初始化基本区间的代价,把长度为1或2这些没有代价的区间置为0,再进行状态转移逐步扩大区间。

code:



#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
const int maxn = 1e2 + 5;
long long dp[maxn][maxn];
int a[maxn];
int main(){
	int n;
	scanf("%d", &n);
	for(int i = 0; i < n; i++) scanf("%d", &a[i]);
	memset(dp, 0x3f, sizeof(dp));
	
	for(int i = 1; i < n - 1; i++)  //初始化
	    dp[i - 1][i + 1] = a[i - 1] * a[i] * a[i + 1];
	    
	for(int k = 0; k < 2; k++)  //如果区间长度为1或2的话,显然他们间没有数可以删,也就没有代价
	   for(int i = 0; i + k < n; i++)
	      dp[i][i + k] = 0;
	      
	for(int k = 3; k < n; k++)  //状态转移
	   for(int i = 0; i + k < n; i++)
	      for(int j = i; j <= i + k; j++)
	          //状态转移式
	         dp[i][i + k] = min(dp[i][i + k], dp[i][j] + dp[j][i + k] + 1LL * a[i] * a[j] * a[i + k]);
	         
	printf("%lld\n", dp[0][n - 1]);
	
} 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值