NOIP 能量项链
题目分析转自:http://www.cnblogs.com/sdjl/articles/1281607.html
此题解析如下:
1、过程很明显,就是合并珠子的过程,从一串珠子共n颗开始,每次合并相邻的两颗为一颗,直到剩下一颗为止。
2、过程的最后一个步骤是把两颗珠子进行合并,这两颗珠子可以这样考虑,其中一颗是连续的r颗合并得到的,另一颗是其余的n-r颗连续的珠子合并得到的,那么选择
就是这个r颗连续的珠子如何选取,以顺时针选取考虑每颗珠子开头的情况,共有n种选择。
3、子问题是选择的这r颗连续的珠子最多能够得到多少能量,以及另外n-r颗连续的珠子最多能够得到多少能量,如果子问题能够得到最优的值,那么母问题在n种选择中
取出最大值则也必然最优,所以符合“最优子结构”。
4、母问题和子问题都是如何在一段珠子中选择一个左、右隔断点,使得最后在隔断点进行合并从而获得最多的能量,不同的是第一个问题需要考虑的是圆形项链,其它
问题需要的是考虑线形项链,因此我们可以把第一个问题选中r颗珠子后剩余的问题(线形的)和子问题(所有子问题都是线形的)看成是重叠的。
5、边界就是仅有一颗或两颗珠子的时候。
6、每一个问题的子问题有两个,都是考虑如何进行合并,因为子问题之间不会使用到同一颗珠子,所以满足独立。
7、用energy[i][j]记录从第i颗珠子到第j颗珠子组成的珠子片断能够得到的最大能量。
8、子问题数为O(n^2),每个问题有O(n)个选择,时间为O(n^3),满足n<=100。
9、参考程序代码。
#include<iostream>
#include<string.h>
using namespace std;
int N;
int value[200];
int dp[200][200];
int max(int a,int b){return a>b?a:b;}
void init()
{
cin>>N;
for(int i=0;i<N;i++)
{
cin>>value[i];
value[N+i]=value[i];
}
memset(dp,0,sizeof(dp));
}
int maxValue(int start,int end)
{
int pauseMaxvalue;
if(dp[start][end]!=0)
{
pauseMaxvalue=dp[start][end];
}
else if(start==end)
{
pauseMaxvalue=dp[start][end];
}else if(start+1==end)
{
pauseMaxvalue=value[start]*value[end]*value[end+1];
}
else
{
pauseMaxvalue=0;
for(int k=start;k<end;k++)
{
int leftvalue=maxValue(start,k);
int rightvalue=maxValue(k+1,end);
int totalvalue=leftvalue+rightvalue+value[start]*value[k+1]*value[end+1];
pauseMaxvalue=max(pauseMaxvalue,totalvalue);
}
}
dp[start][end]=pauseMaxvalue;
return pauseMaxvalue;
}
void show()
{
int MAX=0;
for(int i=0;i<N;i++)
{
MAX=max(MAX,maxValue(i,N+i-1));
}
cout<<MAX<<endl;
}
int main()
{
init();
show();
return 0;
}
posted on 2011-05-31 19:41 lonelycatcher 阅读(1609) 评论(0) 编辑 收藏 举报