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;
    }
    
  • 相关阅读:
    django 自定义用户身份验证
    登录验证算法
    Scrapy
    爬虫性能相关
    Beautifulsoup模块
    selenium模块
    Cookie&Session
    Django Admin 本质
    JavaScript自执行函数和jquery扩展方法
    JS作用域与词法分析
  • 原文地址:https://www.cnblogs.com/kcn999/p/13504249.html
Copyright © 2011-2022 走看看