- 1、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。。
- 2、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载。
- 3、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
- 4、该文档为VIP文档,如果想要下载,成为VIP会员后,下载免费。
- 5、成为VIP后,下载本文档将扣除1次下载权益。下载后,不支持退款、换文档。如有疑问请联系我们。
- 6、成为VIP后,您将拥有八大权益,权益包括:VIP文档下载权益、阅读免打扰、文档格式转换、高级专利检索、专属身份标志、高级客服、多端互通、版权登记。
- 7、VIP文档为合作方或网友上传,每下载1次, 网站将根据用户上传文档的质量评分、类型等,对文档贡献者给予高额补贴、流量扶持。如果你也想贡献VIP文档。上传文档
查看更多
NOIP2006提高组复赛命题与解题报告
1.能量项链(energy.pas/c/cpp)
【问题描述】
在Mars星球上,每个Mars人都随身佩带着一串能量项链。在项链上有N颗能量珠。能量珠是一颗有头标记与尾标记的珠子,这些标记对应着某个正整数。并且,对于相邻的两颗珠子,前一颗珠子的尾标记一定等于后一颗珠子的头标记。因为只有这样,通过吸盘(吸盘是Mars人吸收能量的一种器官)的作用,这两颗珠子才能聚合成一颗珠子,同时释放出可以被吸盘吸收的能量。如果前一颗能量珠的头标记为m,尾标记为r,后一颗能量珠的头标记为r,尾标记为n,则聚合后释放的能量为(Mars单位),新产生的珠子的头标记为m,尾标记为n。
需要时,Mars人就用吸盘夹住相邻的两颗珠子,通过聚合得到能量,直到项链上只剩下一颗珠子为止。显然,不同的聚合顺序得到的总能量是不同的,请你设计一个聚合顺序,使一串项链释放出的总能量最大。
例如:设N=4,4颗珠子的头标记与尾标记依次为(2,3) (3,5) (5,10) (10,2)。我们用记号⊕表示两颗珠子的聚合操作,(j⊕k)表示第j,k两颗珠子聚合后所释放的能量。则第4、1两颗珠子聚合后释放的能量为:
(4⊕1)=10*2*3=60。
这一串项链可以得到最优值的一个聚合顺序所释放的总能量为
((4⊕1)⊕2)⊕3)=10*2*3+10*3*5+10*5*10=710。
【算法说明】
这是根据矩阵连乘问题改编的,是一个典型的动态规划问题。原线性结构改为环状结构,数组扩大一倍(不使用求余方法),比原题略难一些。
矩阵连乘问题是这样描述的:给定n个矩阵 ,每个相邻的矩阵都是可乘的,即前一个矩阵的列数等于后一个矩阵的行数。考察这n个矩阵的连乘积 ,由于矩阵乘法满足结合律,所以计算矩阵的连乘可以有许多不同的计算次序。这种计算次序可以用加括号的方式来确定。以5个矩阵为例,下面一些结合方式都是正确的:
一个m行n列的矩阵与一个n行r列的矩阵相乘,所需要的小乘法(普通的数乘)的次数为。对于n个矩阵连乘,不同的结合顺序所需要的总的小乘法次数一般是不同的。于是,矩阵连乘问题可表述为:对于给定了行数与列数的n个矩阵,如果它们是可乘的,求一种结合顺序,使总的小乘法次数最少。
在我们的问题中,将求最小改为求最大,如果对所有可能结合的方式进行全面搜索,可以证明,对于n个矩阵连乘,不同的结合顺序大约有O(4n)种,当n较大时,显然是行不通的。通常采用动态规划求解。
考虑连乘中的一段:, 设计算A[i:j],1≤i≤j≤n,所需要的最多的乘次数为m[i,j],则原问题的最优值就是m[1,n]。计算A[i,j]的最后一步总是两个矩阵相乘,即 ,因此,可得下面的动态转移方程:
例:设n=4, p0=35, p1=40, p2=20, p3=10, p4=15
即:A1=( )35*40, A2=( )40*20, A3=( )20*10, A4=( )10*15
(1) m12=35*40*20=28000, m23=8000, m34=3000
(2) m13=max {m12+35*20*10, m23+35*40*10}=35000
m24=max {m23+40*10*15, m34+40*20*15}=15000
(3) m14=max{m24+35*40*15, m12+m34+35*20*15, m13+35*10*15} =41500
i 1 2 3 4 1 0 28000 35000 41500 2 0 8000 15000 3 0 3000 4 0 m14就是所求的结果。
函数“void init_neck()”的功能是输入已知数据,再将数组p[]扩大一倍。函数“void matrixch(int p[],int n)”是矩阵连乘的核心算法,注意如果使用int型数,3个下标值相乘时可能会溢出,要做类型转换处理。算法参看附件。函数“void out_neck(int n)”输出最优值,由于是环状的,还要求一次最大值。此题是最容易的一道题。
【参考程序】
#include iostream.h
#include iomanip.h
#include fstream.h
#define N1 100
#define N2 200
long m[N2][N2]={0};
int n,p[N2];
void init_neck()
{int i;
ifstream myinf(energy.in,ios::nocreate);
if(myinf.fail())
{cerrerror opening file myname\n;
文档评论(0)