zjnu(1182)——能量项链

这道题和石子归并其实是同样的题目。

题目链接:http://acm.zjnu.edu.cn/CLanguage/showproblem?problem_id=1182

题意:(那边写的不是很清楚)

首先给你n个珠子,每个珠子都有两个属性,分别是头标记与尾标记,然后分别给出n个数,分别代表的是这些珠子的头标记。

前一颗珠子的尾标记一定等于后一颗珠子的头标记。如果前一颗能量珠的头标记为m,尾标记为r,后一颗能量珠的头标记为r,尾标记为n,则聚合后释放的能量为m×r×n,新产生的珠子的头标记为m,尾标记为n。

因为不同聚合方式产生的能量不同,问你最多能够产生多少能量。

思路:

感觉和石子归并很像。但是因为这里是一个圈,所以我们把它转化为一个链来进行操作。

我们可以将这条链延长2倍,扩展成2n-1堆。(这样我们就使最后一个与第一个连起来了)

其中第1堆与第n+1堆完全相同,第i堆与n+i堆完全相同。这样我们只需对这2n堆进行动态规划后。枚举dp(1,n),dp(2,n),....dp(n,2n-1)去最优值即可。

感想:

这道题让我收获最大的就是利用把环变成链的方式,然后就可以简化问题了。

#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define inf 99999999
#define maxn 222
int s[maxn],a[maxn],dp[maxn][maxn];
int main(){
	int n;
	scanf("%d",&n);
	for(int i=1;i<=n;i++){
		scanf("%d",&a[i]);
	}
	for(int i=1;i<=n;i++){
		if(i==1){
			s[i-1]=s[i-1+n]=a[i];
			s[i]=s[i+n]=a[i+1];
		}
		else if(i==n){
			s[i-1]=a[i];
			s[i]=a[1];
		}
		else{
			s[i-1]=s[i-1+n]=a[i];
			s[i]=s[i+n]=a[i+1];
		}
	}
	int maxx=-1;
	for(int len=2;len<=2*n;len++){
		for(int st=1;st<=2*n-len+1;st++){
			int e=st+len-1;
			dp[st][e]=-1;
			for(int k=st;k<=e-1;k++){
				dp[st][e]=max(dp[st][e],dp[st][k]+dp[k+1][e]+s[st-1]*s[k]*s[e]);  //这里要小心,注意后面那个是dp[k+1][e]以及s[st-1],区分清楚! 
			}
		}
	}
	for(int i=1;i<=n;i++){
		maxx=max(maxx,dp[i][i+n-1]);
	}
	printf("%d\n",maxx);
}
/*
4
2 3 5 10
*/


你可能感兴趣的:(区间dp)