XDOJ1326:生命仪式(环形区间dp)

 



1326: 生命仪式

时间限制: 5 Sec   内存限制: 128 MB
提交: 12   解决: 7

题目描述

tsy的另一个身份是一位mo法师,他准备进行一个生命延续的仪式(为一位长者),仪式的规则是这样的,N个人围成一圈(N号与1号相邻,其余依次相邻),每个人有一个能量值ai,每次选取圈内的一个人进行献祭,这个人立刻退(ren)出(jian)仪(zheng)式(fa),而长者则得到一些时间,时间的大小为选取人选和当前左右两人的能量之积(左右两人在还剩两人时是重复的),最后还剩一人时仪式结束,现在问你怎样操作这个仪式可以使得长者得到的时间总量最大。

输入

多组数据

每组第一行一个数字N代表人数(2 <= N <= 400)

之后N个数字ai代表第i人的能量值(ai <= 150)

输出

一行一个数字,代表得到的最大时间

样例输入

2
4 2

样例输出

32

提示

这不是贪心


来源


环形区间DP的模版题

一个操作代表权值,最后有一个终止条件。

思考什么时候终止便可以得到状态

很显然只剩下一个的时候游戏终止 则状态可以表示为区间i j 取到只剩下i的时候的最大值

状态转移方程

dp[i][j]=max(,dp[i][k]+dp[k+1][j]+a[i]*a[k+1]*a[j+1])

或者也可以将状态标示为剩下I j 其实大体思路是一样的。

#include<bits/stdc++.h>
using namespace std;
const int maxn=410;
long long a[maxn]; 
//相当于合并石子的逆过程
// 
long long dp[maxn][maxn];
typedef long long ll;
ll read(){ 
    ll x=0,f=1;char ch=getchar(); 
    while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();} 
    while(isdigit(ch))x=x*10+ch-'0',ch=getchar(); 
    return f*x; 
}
// 
//dp [i][j] max(dp[i][j],dp[k+1][k-1]+a[k+1]*a[k]*a[k-1]);
int N;
int main(){
	    while(~scanf("%d",&N))
	    {
		for(int i=0;i<N;i++)
		{
			a[i]=read();
		}
		memset(dp,0,sizeof(dp));
		for(int i=1;i<=N;i++)//枚举长度 
		{
       	        for(int j=0;j<N;j++)//枚举左端点 
			{
				int end=j+i%N; 
            	for(int k=j;k<j+i;k++)//中间点 
				{
                   dp[j][end]=max(dp[j][end],dp[j][k%N]+dp[(k+1)%N][end]+a[j]*a[(k+1)%N]*a[(end+1)%N]); 
                   //cout<<i<<" "<<endl;
				}
                }
            }
            long long res=0;
            for(int i=0;i<N;i++)
            {
        	res=max(res,dp[i][(i+N-1)%N]);
	    }
	    printf("%lld\n",res);
	}
	return 0;
} 


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值