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编辑  收藏  举报

导航