主题:进来看看,帮忙解释清楚一点
{说明:}
{动态规划方程:}
{ ans[t,j]= max ( ans[t-1,j+k] ) (其中,k=-2,-1,0,1,2,且相应位置可达)}
program Pizza_For_Free {Time Limit:3000};
{免费馅饼 将允许时间扩大到3000秒,分值限制在longint范围内}
type
link=^linetype; {指向记录一个时间单位决策数组的指针类型}
linetype=array [1..99] of shortint; {记录一个时间单位决策的数组}
var
f1,f2:text; {输入、输出文件变量}
w,h:integer; {宽度、高度}
dd:array [0..100] of array [1..99] of longint; {循环使用的数组,用于表示对应时刻、位置的得分值}
pro:array [0..3100] of link; {记录决策信息的动态数组}
dt:array [0..1,1..99] of longint; {循环使用的动态规划数组}
i,j,k,t:integer; {辅助变量}
bt,bj:integer; {最大状态记录}
best:longint; {最大值记录}
maxt:integer; {最大时间}
ans:array [1..3100] of shortint; {倒推答案时用的暂存区}
num:integer;
pp:longint;
_t,_j,_v:integer; {暂存初始时间、位置、速度}
_fz:longint; {暂存分值}
_saved:boolean; {是否暂存标志}
procedure try_reading; {读入原始数据的过程,其中使用了分段读取的方法。读入初始下落时间不大于t的馅饼}
var
t0,i,j,v:integer; {初始下落时间}
fz:longint; {分值}
begin
fillchar(dd[(t+100) mod 101],sizeof(dd[(t+100) mod 101]),0);
{t及以后时间读入的块,至迟在t+99时间即进入可接收状态,可对t+100(循环观点下)单元清0,以便下次使用}
if _saved then {如果上次有预存}
begin
if _t>t then exit; {如果预存结果仍不被使用到,则返回,否则用预存结果记录新馅饼}
_saved:=false;
if (h-1) mod _v=0 then
begin
inc(dd[(_t+(h-1) div _v) mod 101,_j],_fz);
if (_t+(h-1) div _v)>maxt then maxt:=_t+(h-1) div _v;
end;
end;
if eof(f1) then exit; {文件结束就返回}
while true do {不断读取,直到初始下落时间大于当前处理时间}
begin
if eof(f1) then exit;
readln(f1,t0,j,v,fz);
if t0>t then
begin
_v:=v;
_t:=t0;
_j:=j;
_fz:=fz;
_saved:=true;
exit {暂存返回}
end;
if (h-1) mod v<>0 then continue; {标记时间-位置与得到的分值}
inc(dd[(t0+(h-1) div v) mod 101,j],fz);
if t0+(h-1) div v>maxt then maxt:=t0+(h-1) div v;
end;
end;
begin {主程序}
assign(f1,'INPUT.TXT');
reset(f1);
assign(f2,'OUTPUT.TXT');
rewrite(f2); {文件关联、打开}
readln(f1,w,h); {读入宽、高}
for i:=0 to 3100 do {动态内存初始化}
begin
new(pro[i]);
fillchar(pro[i]^,sizeof(pro[i]^),0);
end;
for i:=0 to 1 do
for j:=1 to 99 do
dt[i,j]:=-maxlongint-1;
{赋初值}
dt[0,(1+w) div 2]:=0; {-maxlongint-1表示该点不可达}
fillchar(dd,sizeof(dd),0);
t:=0;
maxt:=0;
_saved:=false;
try_reading;
best:=0;
bt:=0;
bj:=(w+1) div 2;
best:=dd[0,(w+1) div 2];
while true do
begin
inc(t); {考虑下一个时间}
try_reading; {读入数据}
if eof(f1) and (t>maxt) and not _saved then break; {如果没有新的数据,跳出}
for j:=1 to w do {考虑各个位置}
begin
dt[t mod 2,j]:=-maxlongint-1;
for k:=-2 to 2 do {考虑5种移动方式}
if (j+k>0) and (j+k<=w) and (dt[1-t mod 2,j+k]>-maxlongint-1) {如果可能}
and (dt[1-t mod 2,j+k]+dd[t mod 101,j]>dt[t mod 2,j]) then {而且有效}
begin
dt[t mod 2,j]:=dt[1-t mod 2,j+k]+dd[t mod 101,j]; {更新当前最优值}
pro[t]^[j]:=k;
end;
if dt[t mod 2,j]>best then {如果到目前最优,更新之}
begin
best:=dt[t mod 2,j];
bt:=t;
bj:=j;
end;
end;
end;
writeln(f2,best); {输出最大值}
num:=0;
j:=bj;
for t:=bt downto 1 do {倒推求解}
begin
ans[t]:=-pro[t]^[j];
inc(j,pro[t]^[j]);
end;
for t:=1 to bt do
writeln(f2,ans[t]);
close(f1);
close(f2)
end.
[em2][em2][em2]
{动态规划方程:}
{ ans[t,j]= max ( ans[t-1,j+k] ) (其中,k=-2,-1,0,1,2,且相应位置可达)}
program Pizza_For_Free {Time Limit:3000};
{免费馅饼 将允许时间扩大到3000秒,分值限制在longint范围内}
type
link=^linetype; {指向记录一个时间单位决策数组的指针类型}
linetype=array [1..99] of shortint; {记录一个时间单位决策的数组}
var
f1,f2:text; {输入、输出文件变量}
w,h:integer; {宽度、高度}
dd:array [0..100] of array [1..99] of longint; {循环使用的数组,用于表示对应时刻、位置的得分值}
pro:array [0..3100] of link; {记录决策信息的动态数组}
dt:array [0..1,1..99] of longint; {循环使用的动态规划数组}
i,j,k,t:integer; {辅助变量}
bt,bj:integer; {最大状态记录}
best:longint; {最大值记录}
maxt:integer; {最大时间}
ans:array [1..3100] of shortint; {倒推答案时用的暂存区}
num:integer;
pp:longint;
_t,_j,_v:integer; {暂存初始时间、位置、速度}
_fz:longint; {暂存分值}
_saved:boolean; {是否暂存标志}
procedure try_reading; {读入原始数据的过程,其中使用了分段读取的方法。读入初始下落时间不大于t的馅饼}
var
t0,i,j,v:integer; {初始下落时间}
fz:longint; {分值}
begin
fillchar(dd[(t+100) mod 101],sizeof(dd[(t+100) mod 101]),0);
{t及以后时间读入的块,至迟在t+99时间即进入可接收状态,可对t+100(循环观点下)单元清0,以便下次使用}
if _saved then {如果上次有预存}
begin
if _t>t then exit; {如果预存结果仍不被使用到,则返回,否则用预存结果记录新馅饼}
_saved:=false;
if (h-1) mod _v=0 then
begin
inc(dd[(_t+(h-1) div _v) mod 101,_j],_fz);
if (_t+(h-1) div _v)>maxt then maxt:=_t+(h-1) div _v;
end;
end;
if eof(f1) then exit; {文件结束就返回}
while true do {不断读取,直到初始下落时间大于当前处理时间}
begin
if eof(f1) then exit;
readln(f1,t0,j,v,fz);
if t0>t then
begin
_v:=v;
_t:=t0;
_j:=j;
_fz:=fz;
_saved:=true;
exit {暂存返回}
end;
if (h-1) mod v<>0 then continue; {标记时间-位置与得到的分值}
inc(dd[(t0+(h-1) div v) mod 101,j],fz);
if t0+(h-1) div v>maxt then maxt:=t0+(h-1) div v;
end;
end;
begin {主程序}
assign(f1,'INPUT.TXT');
reset(f1);
assign(f2,'OUTPUT.TXT');
rewrite(f2); {文件关联、打开}
readln(f1,w,h); {读入宽、高}
for i:=0 to 3100 do {动态内存初始化}
begin
new(pro[i]);
fillchar(pro[i]^,sizeof(pro[i]^),0);
end;
for i:=0 to 1 do
for j:=1 to 99 do
dt[i,j]:=-maxlongint-1;
{赋初值}
dt[0,(1+w) div 2]:=0; {-maxlongint-1表示该点不可达}
fillchar(dd,sizeof(dd),0);
t:=0;
maxt:=0;
_saved:=false;
try_reading;
best:=0;
bt:=0;
bj:=(w+1) div 2;
best:=dd[0,(w+1) div 2];
while true do
begin
inc(t); {考虑下一个时间}
try_reading; {读入数据}
if eof(f1) and (t>maxt) and not _saved then break; {如果没有新的数据,跳出}
for j:=1 to w do {考虑各个位置}
begin
dt[t mod 2,j]:=-maxlongint-1;
for k:=-2 to 2 do {考虑5种移动方式}
if (j+k>0) and (j+k<=w) and (dt[1-t mod 2,j+k]>-maxlongint-1) {如果可能}
and (dt[1-t mod 2,j+k]+dd[t mod 101,j]>dt[t mod 2,j]) then {而且有效}
begin
dt[t mod 2,j]:=dt[1-t mod 2,j+k]+dd[t mod 101,j]; {更新当前最优值}
pro[t]^[j]:=k;
end;
if dt[t mod 2,j]>best then {如果到目前最优,更新之}
begin
best:=dt[t mod 2,j];
bt:=t;
bj:=j;
end;
end;
end;
writeln(f2,best); {输出最大值}
num:=0;
j:=bj;
for t:=bt downto 1 do {倒推求解}
begin
ans[t]:=-pro[t]^[j];
inc(j,pro[t]^[j]);
end;
for t:=1 to bt do
writeln(f2,ans[t]);
close(f1);
close(f2)
end.
[em2][em2][em2]