HDU4905--The Little Devil II(四边形不等式优化)

Problem Description
There is an old country and the king fell in love with a devil. The devil always asks the king to do some crazy things. Although the king used to be wise and beloved by his people. Now he is just like a boy in love and can’t refuse any request from the devil. Also, this devil is looking like a very cute Loli.

Y*wan defeat the princess's knight party, and finally he meet the devil. But, after that, y*wan feel in love with the devil and become a lolicon. As the king is already died, y*wan become the new king.

Some days passed, the devil feel bored about this boring country and leaves, but the lolicon remains in the country.

The finally hero, you comes as promised, and you figure out a hard problem to defeat y*wan:

There is n integers a_1,a_2,...,a_n on a line, each time we can take two adjacent integers a and b, and replace them by their gcd(a,b), and add gcd(a,b) to the total score.  The score is initially the sum of all a_i.After n-1 steps there is only one number left and you stop. What is your maximum score in the end?

After defeat y*wan, you kill WJMZBMR, and save the country.
 

Input
The first line contains an integer T, denoting the number of the test cases.
For each test case, the first line contains an integer n.
The next line contains n integers a_1,a_2,...,a_n separated by a single space.

T<=20, n<=3000.
a_i >=0
a_i is in the range of int(C++).
 

Output
For each test case, output the result in one line.
 

Sample Input
  
  
1 4 1 2 2 4
 

Sample Output
再见后来发现此题不满足四边形不等式、、、所以这种做法是错的=_=。不过这不重要。 大笑
  
  
14
给个传送门:http://blog.csdn.net/lmyclever/article/details/6677683
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
#define maxn 3080
int K[maxn][maxn];
int dp[maxn][maxn];
int a[maxn],g[maxn][maxn];
#define LL long long int 
int gcd(int a,int b)
{
	if(!b)	return a;
	return gcd(b,a%b);
}
int main()
{
	int t;
	scanf("%d",&t);
	while(t--)
	{
		int n;	scanf("%d",&n);
		for(int i = 1;i <= n;i++)	
			scanf("%d",&a[i]);
		for(int i = 1;i <= n;i++)
		{
			g[i][i] = a[i];
			for(int j = i+1;j <= n;j++)
				g[i][j] = gcd(g[i][j-1],a[j]);
		}
		memset(dp,0,sizeof(dp));
		for(int i = 1;i <= n;i++)	
		{
			K[i][i] = i;
		}
		for(int i = n;i >= 1;i--)
		{
			for(int j = i+1;j <= n;j++)
			{
				int a = K[i][j-1],b = K[i+1][j];
				if(a<i)	a = i;	if(b>n)	b = n;
				for(int k = a;k <= b;k++)
				{
					if(k+1 <= j && dp[i][j] < dp[i][k]+dp[k+1][j]+g[i][j])
					{
						dp[i][j] = dp[i][k] + dp[k+1][j] + g[i][j];
						K[i][j] = k;
					}
				}
			}
		}
		LL ans = 0;
		for(int i = 1;i <= n;i++)
			ans += a[i];
		ans += dp[1][n];
		cout << ans << endl;
	}
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值