Loading...

NOI 2009 冬令营 · 笔记 (二)

January 18th, 2009 No comments

冬令营17日

 

首先说一下,今天的内容是我目前为止的收获最大的,因为今天的内容很多都涉及到了数学,还有就是晚上论文答辩的时候,吴文虎教授特别提到了一些有关信息学前景以及有关我们学习信息学的目的的问题,吴教授的发言我应该会在冬令营录像发下来之后录进电脑。

 

上午

 

内容: 信息学竞赛中的数学建模初探

授课: 李学武, TGC

 

李学武教授我仰慕很久了,因为李教授在数学理论方面建树颇丰,很有研究。今天听他的讲课更是深有感触。其实学信息学,数学是最重要而且密不可分的模块,不,不是模块,信息学就是数学的一部分,信息学研究的用强大的计算速度解决数学问题,其中有求解的,也有证明的,关于机器证明的那一部分,今年的集训队论文有人提到了,还不够彻底,我记得有一套书叫做《好玩的数学》中有一章就是讲的机器证明,很经典。这部分我以后再谈。

李教授讲的就是有一本数学名著《具体数学》中的一些经典问题,这里我提一下比较重要的部分。

递推关系与求和: 引入是 Josephus (约瑟夫)问题,我们已经知道,关于约瑟夫问题,有模拟的方法可解,但是,有没有更好的方法呢?答案是肯定的,我们观察每次报数出圈,有当前为偶数号的一部分人出圈,接下来,又是新一轮的报数出圈,而且有一部分人成了新的偶数号,我们不难发现,整个出圈的过程,就是一个递归的过程,好,那么我们定义 J(n) 为在有 n 个人的圈上,最后剩下来的人是几号。易得出如下三个递归定义的表达式:

(1)    J(1)=1

(2)    J(2n)=2J(n)-1

(3)    J(2n+1)=2J(n)+1

其中 n 为正整数。

然后我们易得出一个闭形式 (closed form) 的表达式: J(2^m +l)=2l+1.

我们来看一下能不能再化简,我们把 n 化为一个 m 位二进制数,第一位为 B1,最后一位为 Bm,那么我们从那个闭形式表达式惊异地发现,每一次 J(n) 操作,只是把 n 这个二进制数的第一非零位 B1 ,移到 Bm 之后!多么神奇的性质啊!(原因请自己推导)那么,在进行多次 J(n) 操作之后,在进行 J(n) 操作值就会不变了,原因是 n 的所有二进制位都变成 1 了,我们把这样的值叫做“不动点”,这个概念在复合函数中经常提到。多次调用这个函数,不动点会出现在原 n 二进制数中 1 的个数 k 次以下(因为尾部可能有连续的 1),而不动点的值就是 2^(k+1)-1.

我们再把刚刚那些递归定义的式子拓展一下:

(1)    f(1)=α

(2)    f(2n)=2f(n)+β

(3)    f(2n+1)=2f(n)+γ

我们再来尝试用闭形式来描述这些递推式。

观察后知,我们把这个函数写成 f(n)= A(n)α+B(n)β+C(n)γ.

我们列表发现,A(n)事实上是等于 trunc(log n), 而 B(n) 呢,则在 A(n) 不变的周期中随着 n 的增加而从 A(n)-1 递减到 0, C(n) 则恰好相反,在 A(n) 不变的周期中随着 n 的增加而从 0 递增到 A(n)-1. 这些结论,事实上可以由归纳法证明。

接下来,李教授讲了一些关于 sigma 式的化简,由于过于简单,我在这里就不再叙述了。但是李教授提出的思想却是相当好的:

递归<–>求和

  |      |

  >闭形式<

在有诸多表达式形式的情况下,我们要熟练掌握表达式的转化,这样我们才能高效地分析问题,从而解决问题。但这又需要我们有相当扎实的数学理论功底,以前对于名言“数学是无穷的科学”的理解一直停留在“数学题是做不完”的层面(哈哈!),而我们现在发现,数学的代数变换,几何变换,以及数形结合还有最新的机器解题(信息学)等方面的探索是无穷无尽的,数学是最基础的自然科学,它的发展推动着整个科学界的发展。

下午是 TSU 的周源同学讲随机化算法,由于牵扯到很多概率的知识,我留到以后再讲;晚上答辩时吴文虎教授的讲话,我准备单独地写一篇文章,就不在这里写了。

Categories: Informatics Tags:

NOI 2009 冬令营 · 笔记 (一)

January 15th, 2009 1 comment

冬令营 Day 1.

 

上午

内容: 游戏中的数学模型与解题思路

授课人: 吴文虎教授,TSU.

 

今天上午是冬令营的第一堂课,按照惯例,第一堂课都是国际信息学奥林匹克中国队总教练清华大学教授吴文虎教授上的。

吴老一上课就给我们演示了一个“人鬼渡河”游戏,游戏规则是:有3人3鬼在东岸,有一条船容量为2,初始停在东岸,若某一岸(包括停在该岸边的船)上的鬼比人多,那么人就会被鬼吃了。请问如何将3人3鬼安全送到西岸?(注意:船不是电动的,必须要人或鬼划船)。

吴教授首先按照东岸的人数与鬼数表示一个状态:东岸的(人数,鬼数),有一些状态是安全的,有一些是不安全的(东岸或西岸鬼比人多),然后考虑状态的转移方式(即决策),转移(人数,鬼数),有:(1,0),(0,1),(1,1),(2,0),(0,2). 然后我们看我们的转移次数,当目前转移是奇数次时,一定是从东到西,所以是状态量减去决策量;若是偶数,则是从西到东,是状态量加上决策量。接下来我们要考虑判重,当我们东岸状态已经达到过并且船在同一侧时,我们需要剪枝。这样,一个标准的广搜就完成了(最初吴教练是用类似递推的方法,不记录历史状态,其实这样是有反例的:当我们把决策的考虑顺序打乱时,我们很容易走进死胡同,没有历史状态就没法回溯,所以是不正确的)。

休息几分钟后,吴教练开始讲递归,简单介绍了与或节点图,然后又简要地提了一下评估函数,东西都很简单,都是讲一下思想,我在这里就不写了。

 

当然,作为国家队总教练,吴教授讲的都是一些程序设计时的思想方法,比如说人鬼渡河这个例子,我们要从冗长的题目描述中提炼出关键信息,抽象成数学模型,然后从考虑数学模型中转移的方式,找到在数学模型中的转移决策,我们就能够很快地找到解决问题的较优方法。

另外,递归思想事实上是很奇妙的,在数学中也有很广泛的应用,还有很有趣的递归构造的分形Sierpinski三角形,以后我接着写吧。

 

下午

内容:IOI 2008 试题分析

授课人:周冬,原国家队队员,TSU.

这个试题分析其实就是简要地分析一下年鉴上的 IOI 2008 试题解法。有兴趣的可以去看看年鉴,我就不写了。

内容:博弈论相关

授课人:余林韵,TSU.

很有意思的课,首先这位同学简要介绍了 TSU 的“BIDU杯”程序设计大赛,然后他介绍了最近一届大赛“TankCraft”的情况,事实上就是 AI 竞赛,选手们的 AI 间互相打游戏,胜者为王。我们看了决赛的几个回放,真的很精彩,AI 算法都很强大。只是有一次出了一点小 Bug ,双方的3辆 Tank 都相持不动,因为双方都采用了预测对方策略的算法,而且两边都预计对方下一步会攻击,所以原地不动,很有意思。接下来,这位同学简要介绍了一下博弈论,提到的有 Nash均衡点 等博弈知识,其中有一个例子很有意思:有两个囚犯带枪准备犯案,被警察抓住了,警察发现他们以前也犯过罪,但找不到证据,于是拘留了他们俩,隔离突击审讯。如果两个都没招,那么他们俩因“非法携带枪支”各判一年;若有一个招了,另一个没招,那么,没招的那个会判15年,招了的那个因为是证人所以没有被起诉;如果两个都招了,则各判10年。我们来看一看 Nash 均衡点 在哪里:甲想如果甲不招,乙很可能会招,甲会判15年,而甲招了的话,有可能不会被起诉,也有可能是被判10年。所以,甲会招。同理,乙也会招。所以他们两个各被判10年。所以这个问题的 Nash均衡点 在两个都招了的状态这。说明 Nash均衡点 对于某些问题并不是最优的方案。

 

晚上

我们去了位于办公楼的机房,很惊讶地发现装的系统是基于 Ubuntu (Linux) 的 NOI Linux 系统,是中国计算机学会 (CCF) 联合北京航空航天大学开发的一套系统,包括一套开源的信息学竞赛 IDE 系统和一套信息学竞赛评测系统,估计 NOIp 2008 就是在这个环境下评测的。很不错的一套系统。

Categories: Informatics Tags: ,

Pascal 中的操作符定义与重载操作符定义

November 2nd, 2008 No comments

用 Vista 的感觉很好。我一直没用过 Vista ,现在 Vista 和 Windows 7 一起用,感觉真不错哈!

看了柯南兄的Blog,感觉他的操作符描述很模糊,在这里我想讲一遍。

不多废话了:

    1 program cnPhil_operator;
    2 
    3 operator **(a,b:longint)p:longint;//定义双longint**操作
    4 var q:real;
    5 begin
    6      q:=exp(b*ln(a));
    7      p:=trunc(q);
    8 end;
    9 
   10 operator **(a,b:string)p:longint;//定义双string**操作,注意声明同名运算符时,运算量类型一定不能一样,比如有了一个双integer的-操作,你不能再次声明双integer的-操作,但是你可以声明双string的-操作,否则会重载!
   11   var
   12     i,j:longint;
   13     ok:integer;
   14   begin
   15        val(a,i,ok);
   16        val(b,j,ok);
   17        p:=trunc(i**j);//调用以前声明的双longint的**操作,其实运算符声明也可以递归实现!但此处不是递归,而是利用了运算符可以因不同运算量类型而重复定义的特性。
   18   end;
   19 
   20 
   21 
   22 
   23 begin
   24         writeln('2^3=',2**3);
   25         writeln('''2''^''3''=','2'**'3');
   26 end.
另外贴一张我的本本跑 Vista 的图,现在我的本本可是四系统啊(XP,Vista,Win7,Ubuntu),很强吧?
发件人 cnPhil/Photo
Categories: Informatics Tags: ,

长郡NOIp2008停课集训试题解题报告&测试数据 – 10月28日

October 28th, 2008 1 comment

测试数据和完整解题报告在此下载: DropBox | Skydrive

正文:

10月28日_G122_cnPhil_的解题报告

先看哈:

选手列表

编号 姓名 总分

02.mt 02.mt 400.00

standard standard 400.00

–测试器上一角,Orz mt大牛。

简单题目

Easy

时间限制:1s

空间限制:128M

【题目背景】

经典题目自有经典算法。

 

【题目描述】

给你一个N*MN,M<=1000)的01矩形,求一个面积最大的不包含数字1的矩形。

 

【输入数据】

第一行两个数NM

接下来N行,每行M个数为01

 

【输出数据】

一个数ans表示最大空矩形的面积。

Sample

Easy.in

2 4

1 0 0 0

0 1 1 0

 

Easy.out

3

Solve:

这道题,我是用类动规方法做的。对于一个点,记录其竖直向上、水平向左两条最大可以达到多长,再根据这个点左边、上面的点的值求出以这个点为右下角的矩形最大能达到多少。mlj的方法:枚举每列,求出每两个1或边界之间的最大可取矩形。(预处理时标记每点最左最右双向可取长度)

SB

SB

时间限制:1s

空间限制:128M

【题目背景】

题如其名啦……

【题目描述】

给你一棵NN<=10000)个节点的树,求每个点到其他点的最大距离。

【输入数据】

第一行一个数N

接下来若干行每行两个数kt描述一条点k到点t的边(输入数据保证无重复边)。

【输出数据】

N行每行一个数表示每个点到其他点的最大距离。

Sample

SB.in

5

1 2

1 3

1 4

4 5

SB.out

2

3

3

2

3

Solve:

这道题,有个两遍深搜的方法:首先对于每个点,先构造树结构(任选一点作为根),回溯时求出它到底层的最长路和次长路,然后再对于每个点i,枚举这个点到根的每个点j,若这一段ij不在j的最长路上,那么用ij长+j的最长路更新i点值,若这一段ij在j的最长路上,那么用ij长+j的次长路更新i点值。另外还有一个树形动规的方法,貌似很难实现:从底层到根,一层一层来,对于一条边u,v,求出去除其后,以u为根,最长的一条 路径(有边就是路,不管是子是父)就等于u连出的边的目标点的最长路径值,然后对v为根也做一遍。最后,加一个废点指向根,求出经过根的最长路径。这个方法被指有误!不知道是我听错了还是怎么地。哪位大牛能给我讲讲这个树形动规的方法?

判断

Compare

时间限制:1s

空间限制:128M

【题目背景】

这不是道水题!这真的不是道水题!这绝对不是道水题!!!

【题目描述】

给你一个n(n<=1000)个点m(m<=n*n-1/2)条边的图和k(k<=100)程序对这个图做从点1到点n的最短路后得到的的结果,写一个compare判断谁的输出最优。

【输入数据】

第一行三个数nmk

接下来m行,每行三个数abdata表示点a到点b有一条长度为data的无向边(任意两点间最多只有一条边)。

接下来k行,每行为一个程序得到的路径方案(保证路径方案的长度不超过2000)

【输出数据】

如果所有输出均不合法,输出’Wrong‘,否则输出一个保留4位小数的实数,表示k个人得出结果中最小的一条合法路径长度。

Sample

Compare.in

3 3 4

1 2 5.2000

2 3 3.5000

3 2 6.0000

1 2 3 2 3 2 3 2 3 2 3 2 3

1 2 2 3 3 3

1 3

1 3 2 3

Compare.out

8.7000

Solve:

我觉得这道题目内容和上一道题的标题很配。

最优序列

Best

时间限制:1s

空间限制:128M

【题目背景】

背景的意义就是没人看得懂……

题目的意义就是没人做得出……

【题目描述】

给出一个长度为n(n<=1000) 的正整数序列,求一个子序列,使得原序列中任意长度为m 的子串中被选出的元素不超过k(k<=m<=10) 个,并且选出的元素之和最大。

【输入数据】

第一行三个数n,m,k 

第二行n 个数,表示各元素数值大小。

【输出数据】

一个数,表示最大元素和。

Sample:

Best.in

10 4 2

7 3 4 8 2 6 5 7 4 8

Best.out

36

Solve:

与其说是动规,还不如说是搜索。以一个二进制串表示状态情况,然后考虑第i个取不取时,若第i-m个状态值为0,那么这个i状态值一定为0,否则枚举0,1。冷吧!

Categories: Informatics Tags: ,

长郡NOIp2008停课集训测试解题报告 – 10月27日

October 27th, 2008 8 comments

呃,今天电脑有点卡。

测试数据和解题报告完整版在这里下载:DropBox, Skydrive

正文:

老师的询问
题目描述:

东汉末年,颖川书院,有一日老夫子给他的学生出了一道问题,书院中有一口清澈见底的池塘(什么都看得见),老夫子要吃鱼,池塘里有很多很多鱼,而池塘是一个n*m的矩形,他希望放置最少的挡板,将池塘分成很多个矩形(包括正方形),使得每个矩形里有且只有一条鱼,而作为老夫子学生的郭嘉很想完成这个任务,所以他把这个任务交给了你,他相信作为长郡中学未来希望的你肯定不差,希望你能很快地解决问题。

例如:
  n=4m=3时的一种情况(0表示小方格内无鱼,1表示有鱼)。
0 1 0
0 0 0
1 0 1
0 0 0
  可以这么分:

0 1 0

0 0 0

——
1|0 1
0|0 0
  由于池塘边框不需要放置挡板,所以这个分割方案所需的挡板总长度为5
输入数据:
第一行有两个整数nm1n,m32),描述池塘规模。接下来的n行,每行有m个数字(非“0”即“1”)。每两个数字之间用空格隔开。

输出数据:
对于每组输入数据,输出一行:一个数字,所需挡板的最短总长度。

输入样例:
4 3

0 1 0
0 0 0

1 0 1
0 0 0

输出样例:
5

Solve:

    这一道题mt大牛说用类A*算法,先广搜(枚举每条鱼的矩形),检验状态重复,然后用貌似很不必要的方法剪枝。

袁绍的刁难

题目描述:

黄巾之乱后,郭嘉到了袁绍的统辖地区,结果袁绍想给我们的郭嘉大大一个下马威,且正值他招募将领的时候,于是乎,袁绍就让郭嘉大大去替他招募将领。
  这时候有很多很多的将领到袁绍处报到(别人家底厚,四世三公哪~~),每个将领的编号依次为123……N,第i个将领的武力值为3^(i-1)
  袁绍需要我们的郭嘉大大招纳任意个将领,而郭嘉选中的将领有一个“总武力值”为各个将领的武力值之和。例如:郭嘉这一次招募了第一个将领和第三个将领,那么“总武力值”为1+9=10
  袁绍想知道,他可以获得的第k小的“总武力值”是多少,请你帮助我们的郭嘉大大告诉袁绍这个第k大的“总武力值”。
  从文件中读入k,输出郭嘉能够获得的,第k大的“总武力值”。

输入:
  数据包含n+1行,第一行读入n(n100)。以下n行每行包含一个k

输出:
  输出包含n行,每行输出一个对应的结果。 

输入样例:
1
7

输出样例:
13

样例说明:
  郭嘉能够拿到的总武力值从小到大为1349101213……所以第7小的总武力值是13
  对于50%的输入文件,有k5000
  对于100%的输入文件,有k2^31-1
Solve:

这道题是很典型的数学归纳题,类似NOIp2006普及组的第三题,把每一个k请求转成2进制,再把这个二进制数乘以三进制的位权(101=>1*3^2+0*3^1+1*3^0),这样就是结果。这是应用排列组合的方法。自己多模拟模拟就可以发现规律。

游历的路线

题目描述:

    我们的郭嘉大大经过一段时间发现了袁绍这个人干大事而惜身,见小利而忘义,又逢曹操在招兵买马,决定逃离袁绍去投曹操,而我们的曹操在第M天招募良材,我们的郭嘉大大既不能早去,也不能晚去,于是乎,他就趁着这一段时间到其他的城市游历一番,而每两个城市之间只能坐马车来往,由于我们的郭嘉大大很贪钱,他想用最少的费用,所以需要我们帮他求出这一个最小的费用。

输入:

第一行包含两个数nm, 表示有n个城市,和m天后曹操招纳良材。城市一就是郭嘉所在的城市,城市n就是曹操处。接下来n * (n – 1)行描述马车乘坐表。第2到第n行就是描述的城市12… n的马车乘坐表,第n + 1到第2n-1行描述的城市2到城市13..n的马车乘坐表… … 对每一行,首先有一个数T,表示城市I到城市J的马车以T为周期,接下来有T个数,表示每天的马车的价格,如果价格为0则表示没有马车可坐。

n <= 100,  m <= 200,  T <= 20 Price <= 50000
输出:

如果存在这样的路线使郭嘉第m天到达曹操处,则输出最少的费用,否则输出0

输入样例:                             

3 5                                       

2 130 150

3 75 0 80

2 110 100

4 60 70 60 50

3 0 135 140

2 70 80

输出样例:

355

Solve:

    F[i,j]表示第i天到第j个城市的最小花费,

    则有:F[i,j]=Min{F[i-1,k]+Effort(i-1,k,j)}  1<=k<=n

    F[n,m]即为所求。

消息的传递

题目描述:

我们的郭嘉大大在曹操这过得逍遥自在,但是有一天曹操给了他一个任务,在建邺城内有N<=1000)个袁绍的奸细,将他们从1N进行编号,同时他们之间存在一种传递关系,即若C[ij]=1,则奸细i能将消息直接传递给奸细j

现在曹操要发布一个假消息,需要传达给所有奸细,而我们的郭嘉大大则需要传递给尽量少的奸细使所有的奸细都知道这一个消息,问我们至少要传给几个奸细

输入:

    文件的第一行为N,第二行至第N+1行为N*N的矩阵(若第I行第J列为1,则奸细I能将消息直接传递给奸细J,若第I行第J列为0,则奸细I不能将消息直接传递给奸细J)。

输出:

    输出文件只有一行:即我们的郭嘉大大首先至少要传递的奸细个数。

 

输入样例:                             

8

0 0 1 0 0 0 0 0 

1 0 0 1 0 0 0 0 

0 1 0 1 1 0 0 0 

0 0 0 0 0 1 0 0 

0 0 0 1 0 0 0 0 

0 0 0 1 0 0 0 0 

0 0 0 1 0 0 0 1

0 0 0 0 0 0 1 0

输出样例:

2

Solve:

    很经典的图论题目哦。

    首先,求出图中所有强连通分量(Strongly Connected Component, SCC),然后把每个强连通分量缩为一个“点,此时原图就变成了一个标准的拓扑图。入度为0的“点”即为所求。

    强连通分量的求法:(这里给出刘铮同学的求出一个点所在的强连通分量的过程)

procedure zuo(r:longint);

var

  i,j,q:longint;

begin

  inc(p);  //建栈

  b[p]:=r;//r点入栈

  a[r]:=p;//r点在栈中的位置

  c[r]:=p;//r点能连出的最前的点,初值为自己。(link

  i:=v3[r];//选边集数组中r出的一条边。

  while i<>0 do begin

    j:=v1[i];//得到当前边的目标结点

    if(d[j]=0)then begin//如果j点当前不属于任何强连通分量

      if a[j]=0 then zuo(j);//并且j没有进栈,则求j的强连通分量

      if(c[j]<c[r])and(a[j]<>0) then c[r]:=c[j];//jlink值在r之前,且j未出栈,则更新link

    end;

    i:=v2[i];//下一条r出的边

  end;

  if c[r]=a[r] then begin//r不能连到前面,则rr栈以后的点全部出栈。

      q:=a[r];

      for i:=a[r] to p do begin

        d[b[i]]:=r;

        a[b[i]]:=0;

        c[b[i]]:=0;

      end;

      p:=q-1;

  end;

end;

Categories: Informatics Tags: ,

高斯消元法(Gauss Elimination)

October 20th, 2008 2 comments

高斯消元法是一个解线性代数方程组的重要消元法,其重要作用是可以应用于计算机的解线性方程。应为通过它可以构造一个三角矩阵(又称行梯阵式),然后通过迭代的方法求解。

根据高斯消元法的理论,我们只需要n个系数非零的n元方程,即可求解这一方程组。

所以讨论一个n元的行梯阵式,我们只需要看前n行,即可求解。

高斯消元法把一个阵式构造成行梯阵式(三角矩阵)的过程是(只讨论n元矩阵的前n行):设要求解的未知数分别为x1,x2,x3……xn,有R1……Rn个线性方程,线性方程Ri中xj的系数为aij,则用-(ai1/a11)R1加上Ri来消除Ri的x1项,其中i>1。接下来,同样地,用-(aij/ajj)Rj加上Ri来消除Ri的xj项,其中i>j,且Rj……Rn的x1……x(j-1)项应已被R1……R(j-1)消除。

太抽象了?我给出3*3矩阵的求行梯阵式的过程。

算出行梯阵式后,可以将Rn(即xn)代入R(n-1)求出x(n-1),然后将xn,x(n-1)代入R(n-2)求x(n-2),……,一直迭代到求出x1.

懂了吗?呵呵,我的数学研究方向已经从计算机偏向自然科学了。

NOIp 模拟测试解题报告(1)

September 20th, 2008 1 comment

第一题:给出一串已经拓扑好了的事件,求最短完成时间。

做滥了的题目啊,直接扫一边就出解,O(n)

 

第二题:给出第二周的歌曲排行榜和每首歌的歌曲排名变化(上升、下降、持平),求前一周的歌曲排行榜的一种可能解。

字符串处理的题目;

首先,我们把上升了的歌看作要把它往下移,而下降了的歌呢就看作要把它往上移,再把所有的持平歌去掉

那么,现在的排行榜的首位肯定是下,而末位肯定是上了。

现在,找所有下一位是上的下节点。从这个下节点往上延伸到所有连着的下节点,而从这个上节点往下延伸到所有连着的上节点,把这两个模块互换即可。

第三题:你向银行贷款,告诉你你的贷款额、每月还款额和还款月数。求每个月的月利率(每个月银行先算利再让你还钱)

初以为这道题目十分简单,发现不然,这个题目列出来是个高次方程。其实是可以用log函数来解,但是对于有未知数的log函数,Pascal语言显得十分麻烦(几乎不可能实现)。所以,我在考试的时候使用了枚举的方法,得了60%的点。

但是我竟然忘记了世上有二分这样的好方法,其实,以你的总还款额/贷款额的利率(这个是绝对不可能达到的)为上界,下界为0,来二分求解,效果很好。但是虽然二分时间不超,但是发现有一个点竟然超过了int64和extended的届,呵呵。

第四题:走迷宫变形,有起始朝向,就是一秒钟内可以走1格、2格、3格,而且向左向右转也要耗费一秒。

爆容易的题目,难得写了。只有50×50的大小,不说广搜,深搜都能过啊。

课后孟LJ简单阐述了下搜索的优化,无非以下三种:

1、双向广搜(省时一半,较容易实现);

2、普通判断剪枝(子树);

3、估价函数剪枝(A*)。这种做法需要良好的估价能力,适合要打路径的题目。估价函数是一个可以求出从当前状态到目标状态的大概花费的函数,其值必须小于等于真实花费。所以,当走到一个(当前花费+估价花费>已知最小花费)的点时,完全可以把他的子树剪掉。这就是一种动态剪枝方法。效果甚佳,但本人未实现。

Categories: Trivia Tags: ,

NOIp 2000 提高组解题报告

September 9th, 2008 No comments

题一   进制转换:

负进制,短除法,但是余数小于0时要从上一位借位(商+1,余数-进制数)(LRJ大牛提出)

 

题二   乘积最大:

动规+递归

设d(i,j,k)为第i-j个数字中用k个乘号所取得的最大乘积。

转移方程(我直接用递归调用 ^_^):

d(i,j,k)=max{数(第i到第t个字)*d(t,j,k-1)}   (i<=t<=j-1)

临界:所有k=0的值就为原来的值。

 

题三   单词接龙:

求出一张表示每两个单词(有序)之间的增长字母数的表,根据这张表枚举第一个单词来搜。居然全不超时。但是发现有的单词可以用两遍,囧。

 

题四   方格取数:

一直没想通。LRJ的报告太草了。飞机的报告里面是“广搜式Dp,效率还不错。可能数据比较弱。”,囧;

Google了一下,发现“上帝的右手”大牛的报告不错:

两条路线同时进行的动态规划

阶段:按所走的步数来分阶段,从左上角走到右下角,共2n-1个步骤,故共2n-1个阶段。但,有两条线路,故每一阶段的状态都会复杂一些。

状态:有两线路同时走,在某阶段的某状态,要用两个坐标来分别表示两线路的两个点。如:第一阶段,共一个状态:(1,1),(1,1);第二阶段,(1,2),(1,2);(1,2),(2,1);(2,1),(1,2);(2,1),(2,1)共四个状态。

  由于在第k阶段的任何两个点的x,y坐标是有关系的:k+1=x+y。故可只用x坐标来表示一点的坐标,故状态可表示为(x1,x2),对应的y坐标为:y1=k+1-x1,y2=k+1-x2。

决策:若用0,1分别表示向下或向右走,则每个状态的可能决策有四种:(1,1),(0,0),(1,0),(0,1)。两个数值分别表示两个点的下一步走向。

状态转移方程:

  设map(x,y)为方格图,f(k,x1,x2)表示第k个阶段走到(x1,x2)状态的最大和

  f(0,1,1)=map(x1,1+1-x1) 即map(1,1)

  f(k,x1,x2)=max{f(k-1,x1′,x2′)+map(x1,y1)|x1=x2,f(k-1,x1′,x2′)+map(x1,y1)+map(x2,y2)|x1<>x2} (x1′,x2′)表示可通过某决策到达(x1,x2)的所有点

 

明天再把第四题实现一下,就要进入恐怖的2001后了。。。

Categories: Trivia Tags: