凸多边形的划分 区间dp
Posted 行码棋
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了凸多边形的划分 区间dp相关的知识,希望对你有一定的参考价值。
原题链接
状态表示:
f
[
i
]
[
j
]
[
k
]
f[i][j][k]
f[i][j][k]表示选择以第i
个点开头,以第j
个点结尾的围成凸多边形的最小值,k是为了写高精度对第三维做的扩充,表示数的每一位。
转移方程:
f
[
i
]
[
j
]
=
m
i
n
(
f
[
i
]
[
j
]
,
f
[
i
]
[
k
]
+
f
[
k
]
[
j
]
+
w
[
i
]
∗
w
[
j
]
∗
w
[
k
]
)
f[i][j] = min(f[i][j], f[i][k] + f[k][j] + w[i] * w[j] * w[k])
f[i][j]=min(f[i][j],f[i][k]+f[k][j]+w[i]∗w[j]∗w[k])
因为数的范围太大,需要使用高精度写,故对状态增加一维
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 105,M = 34,inf = 0x3f3f3f3f;
int a[N];
ll f[N][N][M];
int n;
//大数相乘
void mul(ll a[],ll b)
{
static ll c[M];
memset(c,0,sizeof c);
ll t = 0;
for(int i=0;i<M;i++)
{
t += a[i] * b;
c[i] = t%10;
t /= 10;
}
memcpy(a,c,sizeof c);
}
//大数相加
void add(ll a[],ll b[])
{
static ll c[M];
memset(c,0,sizeof c);
int t = 0;
for(int i=0;i<M;i++)
{
t += a[i]+b[i];
c[i] = t%10;
t /= 10;
}
memcpy(a,c,sizeof c);
}
//比较多位数
int cmp(ll a[],ll b[])
{
for(int i=M-1;i>=0;i--)
if(a[i]>b[i]) return 1;
else if(a[i]<b[i]) return -1;
return 0;
}
//打印多位数
void print(ll a[])
{
int p = M-1;
while(p>=0 && !a[p]) p--;
while(p>=0) cout<<a[p--];
cout<<'\\n';
}
int main()
{
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
ll temp[M];
for(int len=3;len<=n;len++)
{
for(int l=1;l+len-1<=n;l++)
{
int r = l + len-1;
f[l][r][M-1] = 1;
for(int k=l+1;k<r;k++)
{
memset(temp,0,sizeof temp);
temp[0] = a[l];
mul(temp,a[k]);
mul(temp,a[r]);
add(temp,f[l][k]);
add(temp,f[k][r]);
if(cmp(temp,f[l][r])<0)
memcpy(f[l][r],temp,sizeof temp);
}
}
}
print(f[1][n]);
return 0;
}
以上是关于凸多边形的划分 区间dp的主要内容,如果未能解决你的问题,请参考以下文章