1. 程式人生 > >凸多邊形的劃分

凸多邊形的劃分

題目描述

給定一具有N個頂點(從1到N編號)的凸多邊形,每個頂點的權均已知。問如何把這個凸多邊形劃分成N-2個互不相交的三角形,使得這些三角形頂點的權的乘積之和最小?

輸入輸出格式

輸入格式:

第一行 頂點數N(N<50)。 第二行 N個頂點(從1到N)的權值,權值為小於32768的整數。

輸出格式:

一行,為各三角形頂點的權的乘積之和最小值。

輸入輸出樣例

輸入樣例#1: 
5 
121 122 123 245 231
輸出樣例#1: 
12214884

思路:

設dp(i,j)表示i到j這一段連續的n邊形劃分成兩部分後最小乘積

暴力列舉i到j之間頂點k

轉移方程:dp[i][j]=min(dp[i][j],(dp[i][k]+dp[k][j]+a[i]*a[j]*a[k]))

具體思路可以參考別的部落格

說幾個我犯的智障錯誤

a陣列開成int後面資料型別轉換出了點小問題;忘記三角形三個頂點不能重合;dp陣列忘記初始化然後魔怔般瘋狂輸出0

這種。

以下程式碼

#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#define ll long long

using namespace std;

int n;
ll a[100];
ll dp[100][100];

int main()
{
	memset(dp,0x3f,sizeof(dp));
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
		scanf("%lld",&a[i]);
	for(int i=n;i>=1;i--)
	{
		for(int j=i+1;j<=n;j++)
		{
			if(j-i==1)//容不下一個三角形(參見上述錯誤。)
				dp[i][j]=0;
			else if(j-i==2)
                dp[i][j]=a[i]*a[i+1]*a[i+2];//因為此時i和j中間只剩一個頂點了所以直接計算即可
            else
            	for(int k=i+1;k<=j-1;k++)
            	{
            		dp[i][j]=min(dp[i][j],(dp[i][k]+dp[k][j]+a[i]*a[j]*a[k]));
				}
		}
	}
	printf("%lld",dp[1][n]);
	return 0;
}