环形DP学案.docVIP

  1. 1、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。。
  2. 2、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载
  3. 3、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
  4. 4、该文档为VIP文档,如果想要下载,成为VIP会员后,下载免费。
  5. 5、成为VIP后,下载本文档将扣除1次下载权益。下载后,不支持退款、换文档。如有疑问请联系我们
  6. 6、成为VIP后,您将拥有八大权益,权益包括:VIP文档下载权益、阅读免打扰、文档格式转换、高级专利检索、专属身份标志、高级客服、多端互通、版权登记。
  7. 7、VIP文档为合作方或网友上传,每下载1次, 网站将根据用户上传文档的质量评分、类型等,对文档贡献者给予高额补贴、流量扶持。如果你也想贡献VIP文档。上传文档
查看更多
环形DP学案

怎样实现环形动态规划问题 湖南省醴陵第一中学 曾妞妞 有些动态规划问题的模型是一个环形,比如,vijos上p1312的能量项链、p1218的数字游戏、usaco第一章中破碎的项链、rqnoj上p490的石子合并等问题。环形DP相对线性DP来说,难度增加了,对于环形DP这一类问题怎样解决?其基本的方法思想是怎样的?下面以NOIP2003提高组复赛的第二题数字游戏举例说明。 【2003提高】数字游戏(Game) 一、问题描述 丁丁最近沉迷于一个数字游戏之中。这个游戏看似简单,但丁丁在研究了许多天之后却发觉原来在简单的规则下想要赢得这个游戏并不那么容易。游戏是这样的,在你面前有一圈整数(一共 n 个),你要按顺序将其分为 m 个部分,各部分内的数字相加,相加所得的 m 个结果对 10 取模后再相乘,最终得到一个数 k。游戏的要求是使你所得的 k 最大或者最小。例如,对于下面这圈数字(n=4,m=2): 当要求最小值时,((2-1) mod 10)×((4+3) mod 10)=1×7=7,要求最大值时,为((2+4+3) mod 10)×(-1 mod 10)=9×9=81。特别值得注意的是,无论是负数还是正数,对 10 取模的结果均为非负值。 丁丁请你编写程序帮他赢得这个游戏。 【输入格式】 输入文件第一行有两个整数,n(1≤n≤50)和m(1≤m≤9)。以下n行每行有个整数, 其绝对值不大于10,按顺序给出圈中的数字,首尾相接。 【输出格式】 输出文件有两行,各包含一个非负整数。第一行是程序得到的最小值,第二行是最大值。 【输入样例】 4 2 4 3 -1 2 【输出样例】 7 81 二、解题思路由于此题采用了环的设计,首先第一步肯定是针对环进行断链比如这样一个环处理比如这样一个环program number; var fmin,fmax,sum:array[0..50,0..50]of longint; b,a:array[0..50]of longint; i,j,n,m:longint; max,min:int64; procedure doit;{动态规划计算一条链分成m部分的最大值与最小值。} var i,j,k:longint; begin filldword(fmin,sizeof(fmin)div 4; fillchar(fmax,sizeof(fmax), 0); for i:=1 to n do begin fmin[i,0]:=sum[1,i];fmax[i,0]:=sum[1,i]; end; {fmax[i,k]表示前i个数切成m部分的最大值,k表示切的刀数} for k:=1 to m-1 do for i:=k+1 to n do for j:=1 to i-1 do begin if fmax[i,k]fmax[j,k-1]*sum[j+1,i] then fmax[i,k]:=fmax[j,k-1]*sum[j+1,i]; if fmin[i,k]fmin[j,k-1]*sum[j+1,i] then fmin[i,k]:=fmin[j,k-1]*sum[j+1,i]; end; {前i个数分成m部分等价于把前j个数分成m-1部分,从j+1到i分成1部分} if fmax[n,m-1]max then max:=fmax[n,m-1];{记录最大值} if fmin[n,m-1]min then min:=fmin[n,m-1]; {记录最小值} end; procedure makesum;{计算任意两个数之间的数字相加的结果对 10 取模。} var i,j:longint; begin for i:=1 to n do for j:=i to n do sum[i,j]:=((sum[i,j-1]+a[j])mod 10+10)mod 10; end; begin readln(n,m); max:=0;min:=maxlongint; for i:=1 to n do read(b[i]); for i:=1 to n do{把环切断成n条链,根据切断位置的不同形成n条不同的链,枚举n个不同的结点作为起点结点时的最大值} begin fillchar(a,sizeof(a),0); fillchar(sum,si

文档评论(0)

wuyuetian + 关注
实名认证
文档贡献者

该用户很懒,什么也没介绍

1亿VIP精品文档

相关文档