【NOI2005】 瑰丽华尔兹

题目描述
瑰丽华尔兹
【任务描述】
你跳过华尔兹吗?当音乐响起,当你随着旋律滑动舞步,是不是有一种漫步
仙境的惬意?
众所周知,跳华尔兹时,最重要的是有好的音乐。但是很少有几个人知道,
世界上最伟大的钢琴家一生都漂泊在大海上,
他的名字叫丹尼·布德曼·T.D.·柠檬·1900,朋友们都叫他 1900190020 世纪的第一年出生在往返于欧美的邮轮弗吉尼亚号上。很不幸,
他刚出生就被抛弃,成了孤儿。1900 孤独的成长在弗吉尼亚号上,从未离开过
这个摇晃的世界。也许是对他命运的补偿,上帝派可爱的小天使艾米丽照顾他。
可能是天使的点化,1900 拥有不可思议的钢琴天赋:从未有人教,从没看过
乐谱,但他却能凭着自己的感觉弹出最沁人心脾的旋律。当 1900 的音乐获得邮
轮上所有人的欢迎时,他才 8 岁,而此时,他已经乘着海轮往返欧美大陆 50 余
次了。虽说是钢琴奇才, 1900 还是个孩子,但他有着和一般男孩一样的好奇和
调皮,只不过更多一层浪漫的色彩罢了:
这是一个风雨交加的夜晚,海风卷起层层巨浪拍打着弗吉尼亚号,邮轮随着
巨浪剧烈的摇摆。船上的新萨克斯手迈克斯·托尼晕船了,1900 招呼托尼和他
一起坐到舞厅里的钢琴上,然后松开了固定钢琴的闸,于是,钢琴随着海轮的倾
斜滑动起来。准确的说,我们的主角 1900、钢琴、邮轮随着 1900 的旋律一起跳
起了华尔兹,随着“嘣嚓嚓”的节奏,托尼的晕船症也奇迹般的消失了。后来托
尼在回忆录上这样写道:
大海摇晃着我们
使我们转来转去
快速的掠过灯和家具
我意识到我们正在和大海一起跳舞
真是完美而疯狂的舞者
晚上在金色的地板上快乐的跳着华尔兹是不是很惬意呢?也许,我们忘记了
一个人,那就是艾米丽,她可没闲着:她必须在适当的时候施展魔法帮助 1900,
不让钢琴碰上舞厅里的家具。
不妨认为舞厅是一个 N 行 M 列的矩阵,
矩阵中的某些方格上堆放了一些家具,
其他的则是空地。钢琴可以在空地上滑动,但不能撞上家具或滑出舞厅,否则会
损坏钢琴和家具,引来难缠的船长。
每个时刻,钢琴都会随着船体倾斜的方向向相邻的方格滑动一格,相邻的方
格可以是向东、向西、向南或向北的。而艾米丽可以选择施魔法或不施魔法:如
果不施魔法,则钢琴会滑动;如果施魔法,则钢琴会原地不动。
艾米丽是个天使,她知道每段时间的船体的倾斜情况。她想使钢琴在舞厅里
滑行的路程尽量长,这样 1900 会非常高兴,同时也有利于治疗托尼的晕船。但
艾米丽还太小,不会算,所以希望你能帮助她。
【输入格式】
输入文件的第一行包含 5 个数 N, M, x, y 和 K。N 和 M 描述舞厅的大小,x
和 y 为钢琴的初始位置;我们对船体倾斜情况是按时间的区间来描述的,且从 1
开始计算时间,比如“在[1, 3]时间里向东倾斜,[4, 5]时间里向北倾斜”
,因此这里的 K 表示区间的数目。
以下 N 行,每行 M 个字符,描述舞厅里的家具。 i 行第 j 列的字符若为‘ . ’,
则表示该位置是空地;若为‘ x ’,则表示有家具。
以下 K 行,顺序描述 K 个时间区间,格式为:si ti di(1 ≤ i ≤ K)。表示在时间
区间[si, ti]内,船体都是向 di 方向倾斜的。di 为 1, 2, 3, 4 中的一个,依次表示北、
南、西、东(分别对应矩阵中的上、下、左、右)
。输入保证区间是连续的,即
s1 = 1
ti = si-1 + 1 (1 < i ≤ K)
tK = T
【输出格式】
输出文件仅有 1 行,包含一个整数,表示钢琴滑行的最长距离(即格子数)。
【输入样例】
45413
..xx.
.....
...x.
.....
134
451
672
【输出样例】
6
【样例说明】
钢琴的滑行路线:
钢琴在“×”位置上时天使使用一次魔法,因此滑动总长度为 6。
【评分方法】
本题没有部分分,你的程序的输出只有和我们的答案完全一致才能获得满
分,否则不得分。
【数据范围】
50%的数据中,1≤N, M≤200,T≤200;
第 3 页 共 10 页
Http://www.noi.cn
100%的数据中,1≤N, M≤200,K≤200,T≤40000


样例说明:

 

题解

 

动态规划(朴素)
 1 (*
 2     *Problem:    瑰丽的华尔兹
 3     *Author :    Chen Yang
 4     *Time   :    2012.6.3 8:30 am
 5     *State  :    70分
 6     *Memo   :    朴素DP
 7 *)
 8 program adv1900;
 9 const
10   move:array[1..4,1..2] of longint=((1,0),(-1,0),(0,1),(0,-1));
11 var
12   n,m,k,x,y,i,j,i1,p,ans,this,past:longint;
13   map:array[0..201,0..201] of char;
14   f:array[0..1,0..201,0..201] of longint;
15   t,s:array[0..300] of longint;
16 //=========================
17 begin
18   assign(input,'adv1900.in'); reset(input);
19   assign(output,'adv1900.out'); rewrite(output);
20   readln(n,m,x,y,k);
21   for i:=1 to n do
22   begin
23     for j:=1 to m do read(map[i,j]);
24     readln;
25   end;
26   for i:=1 to k do
27   begin
28     read(j,i1,s[i]);
29     t[i]:=i1-j+1;
30   end;
31   fillchar(f,sizeof(f),200);
32   this:=1; past:=0;
33   f[this,x,y]:=0;
34   for i1:=1 to k do
35   begin
36     this:=this xor 1; past:=past xor 1;
37     fillchar(f[this],sizeof(f[this]),200);
38     for i:=1 to n do
39     for j:=1 to m do
40     if map[i,j]='.' then
41     begin
42       for p:=0 to t[i1] do
43       begin
44         //writeln(x,' ',y);
45         x:=i+p*move[s[i1],1]; y:=j+p*move[s[i1],2];
46         if (x<1)or(y<1)or(x>n)or(y>m)or(map[x,y]='x') then break;
47         if f[this,i,j]<f[past,x,y]+p then f[this,i,j]:=f[past,x,y]+p;
48       end;
49       //writeln(i1,' ',i,' ',j,' ',f[this,i,j]);
50     end;
51   end;
52   ans:=0;
53   for i:=1 to n do
54   for j:=1 to m do
55   if ans<f[this,i,j] then ans:=f[this,i,j];
56   writeln(ans);
57   close(input); close(output);
58 end.

 

动态规划(单调队列优化)
 1 (*
 2     *Problem:    瑰丽的华尔兹
 3     *Author :    Chen Yang
 4     *Time   :    2012.6.3 12:00 am
 5     *State  :    Sloved
 6     *Memo   :    单调队列优化DP
 7 *)
 8 program adv1900;
 9 var
10   n,m,k,x,y,i,j,i1,ans,this,past,l,r:longint;
11   map:array[0..201,0..201] of char;
12   f:array[0..1,0..201,0..201] of longint;
13   t,s,dui:array[0..300] of longint;
14 //=========================
15 begin
16   assign(input,'adv1900.in'); reset(input);
17   assign(output,'adv1900.out'); rewrite(output);
18   readln(n,m,x,y,k);
19   for i:=1 to n do
20   begin
21     for j:=1 to m do read(map[i,j]);
22     readln;
23   end;
24   for i:=1 to k do
25   begin
26     read(j,i1,s[i]);
27     t[i]:=i1-j+1;
28   end;
29   fillchar(f,sizeof(f),200);
30   this:=1; past:=0;
31   if map[x,y]<>'x' then f[this,x,y]:=0;
32   for i1:=1 to k do
33   begin
34     this:=this xor 1; past:=past xor 1;
35     fillchar(f[this],sizeof(f[this]),200);
36     case s[i1] of
37     1:for j:=1 to m do
38       begin
39         l:=0; r:=0;
40         for i:=n downto 1 do
41         begin
42           if map[i,j]='x' then begin l:=0; r:=0; end;
43           while (l<r)and(dui[l+1]>i+t[i1]) do inc(l);
44           while (l<r)and(f[past,dui[r],j]+dui[r]-i<f[past,i,j]) do dec(r);
45           inc(r); dui[r]:=i;
46           f[this,i,j]:=f[past,dui[l+1],j]+dui[l+1]-i;
47         end;
48       end;
49     2:for j:=1 to m do
50       begin
51         l:=0; r:=0;
52         for i:=1 to n do
53         begin
54           if map[i,j]='x' then begin l:=0; r:=0; end;
55           while (l<r)and(dui[l+1]<i-t[i1]) do inc(l);
56           while (l<r)and(f[past,dui[r],j]+i-dui[r]<f[past,i,j]) do dec(r);
57           inc(r); dui[r]:=i;
58           f[this,i,j]:=f[past,dui[l+1],j]+i-dui[l+1];
59         end;
60       end;
61     3:for i:=1 to n do
62       begin
63         l:=0; r:=0;
64         for j:=m downto 1 do
65         begin
66           if map[i,j]='x' then begin l:=0; r:=0; end;
67           while (l<r)and(dui[l+1]>j+t[i1]) do inc(l);
68           while (l<r)and(f[past,i,dui[r]]+dui[r]-j<f[past,i,j]) do dec(r);
69           inc(r); dui[r]:=j;
70           f[this,i,j]:=f[past,i,dui[l+1]]+dui[l+1]-j;
71         end;
72       end;
73     4:for i:=1 to n do
74       begin
75         l:=0; r:=0;
76         for j:=1 to m do
77         begin
78           if map[i,j]='x' then begin l:=0; r:=0; end;
79           while (l<r)and(dui[l+1]<j-t[i1]) do inc(l);
80           while (l<r)and(f[past,i,dui[r]]+j-dui[r]<f[past,i,j]) do dec(r);
81           inc(r); dui[r]:=j;
82           f[this,i,j]:=f[past,i,dui[l+1]]+j-dui[l+1];
83         end;
84       end;
85     end;
86   end;
87   ans:=0;
88   for i:=1 to n do
89   for j:=1 to m do
90   if ans<f[this,i,j] then ans:=f[this,i,j];
91   writeln(ans);
92   close(input); close(output);
93 end.
posted @ 2012-06-03 20:19  datam  阅读(462)  评论(0编辑  收藏  举报