区间DP凸多边形的划分

Posted Vincent_0000

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了区间DP凸多边形的划分相关的知识,希望对你有一定的参考价值。

题目来源

点我进入ACwing官网提交

题目描述

给定一个具有 N 个顶点的凸多边形,将顶点从 1 至 N 标号,每个顶点的权值都是一个正整数。

将这个凸多边形划分成 N−2 个互不相交的三角形,对于每个三角形,其三个顶点的权值相乘都可得到一个权值乘积,试求所有三角形的顶点权值乘积之和至少为多少。

输入格式
第一行包含整数 N,表示顶点数量。

第二行包含 N 个整数,依次为顶点 1 至顶点 N 的权值。

输出格式
输出仅一行,为所有三角形的顶点权值乘积之和的最小值。

数据范围
N≤50,
数据保证所有顶点的权值都小于 1 0 9 10^9 109
输入样例:
5
121 122 123 245 231
输出样例:
12214884

题目思路

  • 分析题型

成环,在区间中挑点,数据范围不太大,求最小值 − > -> >区间DP问题。
权值太大,需要使用高精度。

  • DP分析

在多边形中需要挑选三个点,对于最基础的区间DP模板,刚好有三个点,且都是变化的,那么就直接以他们做为集合的划分。
结合大数模拟即可得出答案。

  • 边界值

先要将我们的数组初始化为一个很大的值。
然后进行运算,并不会影响结果的,因为是一段一段遍历过来的,所以到遍历一段的时候,长度比他小的那一段已经遍历过了。

  • 目标

f [ 1 ] [ n ] f[1][n] f[1][n]

AC代码

#include<bits/stdc++.h> 
using namespace std;

#define _for(i, a, b) for (int i = (a); i < (b); ++i) 
#define _rep(i, a, b) for (int i = (a); i <= (b); ++i)
#define For(i, a, b) for (int i = (a); i >= (b); --i)
#define debug(a) cout << #a << " = " << a << ENDL
#define ENDL "\\n"
#define x first 
#define y second 
typedef long long ll;
typedef pair<int, int> pii;
typedef vector<int> vi;

const int N = 50 + 5, M = 35;
ll f[N][N][M], w[N];

void mul(ll a[], ll x) {
	ll  t = 0;
	_for(i, 0, M) {
		t += a[i] * x;
		a[i] = t % 10;
		t /= 10;
	}
}

void add(ll* a, ll* b) {
	ll t = 0;
	_for(i, 0, M) {
		t += a[i] + b[i];
		a[i] = t % 10;
		t /= 10;
	}
}

bool cmp(ll* a, ll* b) {
	For(i, M - 1, 0) if (a[i] > b[i]) return true;
	else if (a[i] < b[i]) return false;
	return false;
}

void Print(ll* a) {
	int r = M;
	while (!a[r] && r) --r;
	while (~r) cout << a[r--];
	cout << ENDL;
}

int main() {
#ifdef LOCAL
	freopen("data.in", "r", stdin);
#endif 
	ios::sync_with_stdio(false);
	cin.tie(0), cout.tie(0);

	int n;
	cin >> n;
	_rep(i, 1, n) cin >> w[i];

	_rep(len, 3, n) _rep(l, 1, n - len + 1) {
		int r = l + len - 1;
		f[l][r][M - 1] = 1;
		_for(k, l + 1, r) {
			ll tmp[M] = { 1 };
			mul(tmp, w[l]);
			mul(tmp, w[r]);
			mul(tmp, w[k]);
			add(tmp, f[l][k]);
			add(tmp, f[k][r]);
			if (cmp(f[l][r], tmp)) memcpy(f[l][r], tmp, sizeof tmp);
		}
	}	
	Print(f[1][n]);
	return 0;
} 

反思

这题做之前没有分析出这是一个高精度问题,想着三个数相乘不会爆long long,但是自己没有想到的是他们还要相加。
这个不是错这个题目的根本原因,先分析出来了这是 区间DP,确定区间之后,我却想着再在区间中找两个点,,没有考虑到两边的端点都可以作为动态转移方程的关键变量。

  1. 以后做题一定要分析到时间复杂度以及变量类型。
  2. 先以原始模板思路开始想,然后再进行变形。

以上是关于区间DP凸多边形的划分的主要内容,如果未能解决你的问题,请参考以下文章

凸多边形的划分 区间dp

区间dp

区间DP之凸多边形的三角剖分

Acwing1069. 凸多边形的划分

2/1 dp+区间dp+catalan数+Cayley公式

ZOJ 3537 Cake 求凸包 区间DP