zoukankan      html  css  js  c++  java
  • LOJ 10149 凸多边形的划分

    题目大意

    给定一个具有 (n) 个顶点的凸多边形,将顶点从 (1)(n) 标号,顶点 (i) 的权值为一个正整数 (a_i) 。将这个凸多边形划分成 (n-2) 个互不相交的三角形,试求这些三角形顶点的权值乘积和至少为多少。
    其中, (3 leq n leq 50)(1 leq a_i < 10^9)

    题解

    (f(i,j)) 表示点 (i,i+1,i+2,...j) 组成的凸多边形内进行划分的最小权值乘积和。
    (f(i,j) = minlimits_{i < k < j} left{f(i,k) + f(k,j) + a_i a_k a_j ight})
    如下图:

    也就是划分出粉色三角形,并合并蓝色多边形的贡献 。
    但如果连接 (ik) 不是最优的呢?其实不连接的情况也可以转移出来,画个图就知道了。(然而自己当时想了30min,一直怀疑这样做的可行性)
    所以我们设计状态的时候,当我们觉得某种情况无法转移出来时,要仔细想想是否能从别的情况得到,而不是轻易否定这种状态设计。

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    
    using std::memset;
    using std::min;
    using std::max;
    
    #define MAX_N (50 + 5)
    
    struct Big_Number
    {
    	int bit[35];
    	int len;
    	
    	Big_Number()
    	{
    		memset(bit, 0, sizeof bit);
    		len = 1;
    	}
    	
    	Big_Number operator = (int num)
    	{
    		memset(bit, 0, sizeof bit);
    		len = 0;
    		do
    		{
    			bit[++len] = num % 10;
    			num /= 10;
    		}
    		while (num);
    		return *this;
    	}
    	
    	bool operator < (const Big_Number & x) const
    	{
    		if (len != x.len) return len < x.len;
    		for (int i = len; i; --i)
    		{
    			if (bit[i] != x.bit[i]) return bit[i] < x.bit[i];
    		}
    		return false;
    	}
    	
    	Big_Number operator + (const Big_Number & x) const
    	{
    		Big_Number res;
    		res.len = max(len, x.len);
    		for (int i = 1; i <= res.len; ++i)
    		{
    			res.bit[i] += bit[i] + x.bit[i];
    			if (res.bit[i] >= 10)
    			{
    				++res.bit[i + 1];
    				res.bit[i] -= 10;
    			}
    		}
    		while (res.bit[res.len + 1])
    		{
    			++res.len;
    			if (res.bit[res.len] >= 10)
    			{
    				++res.bit[res.len + 1];
    				res.bit[res.len] -= 10;
    			}
    		}
    		return res;
    	}
    	
    	Big_Number operator * (const Big_Number & x) const
    	{
    		Big_Number res;
    		res.len = len + x.len - 1;
    		for (int i = 1; i <= res.len; ++i)
    		{
    			for (int j = min(i, len); j; --j)
    			{
    				res.bit[i] += bit[j] * x.bit[i - j + 1];
    			}
    			if (res.bit[i] >= 10)
    			{
    				res.bit[i + 1] += res.bit[i] / 10;
    				res.bit[i] %= 10;
    			}
    		}
    		while (res.bit[res.len + 1])
    		{
    			++res.len;
    			if (res.bit[res.len] >= 10)
    			{
    				res.bit[res.len + 1] += res.bit[res.len] / 10;
    				res.bit[res.len] %= 10;
    			}
    		}
    		return res;
    	}
    };
    
    int n;
    Big_Number a[MAX_N];
    Big_Number f[MAX_N][MAX_N];
    
    Big_Number Min(Big_Number x, Big_Number y)
    {
    	if (x < y) return x;
    	return y;
    }
    
    int main()
    {
    	scanf("%d", &n);
    	int tmp;
    	for (int i = 1; i <= n; ++i)
    	{
    		scanf("%d", &tmp);
    		a[i] = tmp;
    	}
    	for (int i = n - 2; i; --i)
    	{
    		for (int j = i + 2; j <= n; ++j)
    		{
    			f[i][j].len = 30;
    			memset(f[i][j].bit, 0x7f, sizeof f[i][j].bit);
    			for (int k = i + 1; k < j; ++k)
    			{
    				f[i][j] = Min(f[i][j], f[i][k] + f[k][j] + a[i] * a[k] * a[j]);
    			}
    		}
    	}
    	for (int i = f[1][n].len; i; --i)
    	{
    		printf("%d", f[1][n].bit[i]);
    	}
    	return 0;
    }
    
  • 相关阅读:
    centos 编码问题 编码转换 cd到对应目录 执行 中文解压
    centos 编码问题 编码转换 cd到对应目录 执行 中文解压
    centos 编码问题 编码转换 cd到对应目录 执行 中文解压
    Android MVP 十分钟入门!
    Android MVP 十分钟入门!
    Android MVP 十分钟入门!
    Android MVP 十分钟入门!
    mysql备份及恢复
    mysql备份及恢复
    mysql备份及恢复
  • 原文地址:https://www.cnblogs.com/kcn999/p/13504249.html
Copyright © 2011-2022 走看看