#4 公司利润 2014-01-16
这真的是动归?怎么觉得有点贪心的心态在。时间复杂度O(N),空间复杂度O(1),轻松加愉快!唯一要注意的是ANS一开始要赋负值,因为最终答案可能是负的。
program usaco_4; var n,i,x,ans,last:longint; a:array[0..100000] of longint; begin ans:=-maxlongint+100; readln(n); for i:=1 to n do begin readln(x); if last>0 then last:=x+last else last:=x; if last>ans then ans:=last; end; writeln(ans); end.
#5 接住苹果 2014-01-17
亲娘说:“我给你榨胡萝卜汁吧,10分钟就好。”我说:“嗯,看我十分钟能不能把这题写出来。”差不多刚好十分钟,因为亲娘用了五分钟不到就榨好了…
a[i,j,p]表示第i只苹果掉落后,经过j次移动,最后一次接苹果是在p树下可以接到的最多苹果树。
可以优化的地方就是,反正计算a[i,j,p]只是和a[i-1,j-1,1..2]和a[i-1,j,1..2]有关嘛,所以不开数组应该也无妨吧。
写的时候犯了两个小错误:(1)for j:=0 to k do 写成了1 to k;(2)把循环里的j都写成了k… 都是脑残错误…
program usaco_5; var a:array[0..1000,-1..30,1..2] of integer; q:array[0..1000,1..2] of word; n,k,i,j,p1,p2,t,ans:integer; begin readln(n,k); for i:=1 to n do begin readln(t); q[i,t]:=1; end; ans:=-32767+10; for i:=1 to n do for j:=0 to k do begin p1:=a[i-1,j,1]+q[i,1];p2:=a[i-1,j-1,2]+q[i,1]; if p1>p2 then a[i,j,1]:=p1 else a[i,j,1]:=p2; if a[i,j,1]>ans then ans:=a[i,j,1]; p1:=a[i-1,j,2]+q[i,2];p2:=a[i-1,j-1,1]+q[i,2]; if p1>p2 then a[i,j,2]:=p1 else a[i,j,2]:=p2; if a[i,j,2]>ans then ans:=a[i,j,2]; end; writeln(ans); end.
BTW,这题因为是NOV04的题目,找数据找了会儿…最后发现只要改这个网址的最后就行了:http://cerberus.delos.com:794/NOV04
#6 方形牛棚 2014-01-17
似乎做过类似的题,似乎知道是四个小正方形拼成一个大的,就是脑残没想出动态转移方程:a[i,j]:=min(a[i-1,j],a[i-1,j-1],a[i,j-1])+1 {a[i,j]表示以(i,j)为右下角可取的正方形的最大边长} 现在处于脑残题也做不来,难题也不会的境界啊…
BTW,此题也是USACO Training 5.3.4。
program usaco_6; var a,map:array[0..1000,0..1000] of word; n,m,i,j,tx,ty,ans:integer; function min(x,y,z:integer):integer; begin min:=x; if y<min then min:=y; if z<min then min:=z; end; begin readln(n,m); for i:=1 to m do begin readln(tx,ty); map[tx,ty]:=1; end; for i:=1 to n do for j:=1 to n do if map[i,j]<>1 then begin a[i,j]:=min(a[i-1,j],a[i-1,j-1],a[i,j-1])+1; if a[i,j]>ans then ans:=a[i,j]; end; writeln(ans); end.
其实做不大的改动也可成为求最大的矩形牛棚的程序。
#7 滑雪课程 2014-01-22
脑残的我回来了,被这道三星的题目坑死!错误主要有以下:
(1)没有考虑有没有获得能力的边界,解决办法:开始都赋初值-1,非-1才表示能力达到,可操作。
(2)work2过程的参数弄错,主程序里的i和过程里的i混了…解决办法,添加参数x,y。
(3)f[i,j]表示第i分钟结束后,以j的能力值可以划的最多次数。在算课程的时候,我不小心把i当开始时间了。解决办法:+1
总之这题从昨天做死都做不出来查不出错,到看别人解题觉得和我自己的一样,到睡觉前想怎么解决到失眠,到今天早上物理课没心情听还在想…啊啊啊我的DP水平是有多糟糕啊…最后程序只有60-行
program usaco_7; type rec=record start,last,level:integer; end; var l:array[0..100] of longint; f:array[-100..10100,1..100] of longint; r:array[0..100] of rec; mark:array[0..10010] of boolean; t,s,n,i,j,c,d,temp,ans,maxa:longint; procedure work2(x,y:integer); var i:integer; begin for i:=1 to s do if r[i].start=x+1 then if f[x,y]>f[x+r[i].last,r[i].level] then f[x+r[i].last,r[i].level]:=f[x,y]; end; begin fillchar(mark,sizeof(mark),false); readln(t,s,n); for i:=1 to s do begin readln(r[i].start,r[i].last,r[i].level); if r[i].level>maxa then maxa:=r[i].level; mark[r[i].start]:=true; end; for i:=1 to 100 do l[i]:=32000; for i:=1 to n do begin readln(c,d); if l[c]>d then l[c]:=d; end; for i:=2 to 100 do if l[i-1]<l[i] then l[i]:=l[i-1]; for i:=0 to t do for j:=1 to maxa do f[i,j]:=-1; f[0,1]:=0; for i:=0 to t do for j:=1 to maxa do begin if f[i,j]<>-1 then begin if f[i,j]>f[i+1,j] then f[i+1,j]:=f[i,j]; if i+l[j]<=t then if f[i,j]+1>f[i+l[j],j] then f[i+l[j],j]:=f[i,j]+1; if mark[i+1] then work2(i,j); end; end; for j:=1 to 100 do if f[t,j]>ans then ans:=f[t,j]; writeln(ans); end.
P.S. 我拿到的题目的output里有注释,坑子的是这个注释竟然是错的!!正确的应该是3-4去上课,5-10在滑雪。
#8 滑雪比赛
终于没看解题,不过做的过程略脑残,一开始只想到转移方程的其一,后来才想到要判断,就是分(1)从T[i]到T[i+1]的路程没办法使速度从S[i]加到S[i+1] (2)从T[i]到T[i+1]的路程没办法使速度从S[i]降到S[i+1] 问题(1)写在转移方程的第二段里,(2)写在前面的预判里,直接对S数组进行处理。我相信还有别的处理方法,总之觉得自己写烦了。
还要注意有可能是通过重点的时候达到最大速度,再特判一个即可。
顺便0-0这真的是动归?我对我自己对DP的理解表示怀疑…第二章至此完美结束。
program usaco_8; var t,s,f:array[0..100000+10] of longint; n,i,j,l,max,temp:longint; procedure qsort(l,r:longint); var i,j,mid,temp:longint; begin i:=l;j:=r;mid:=t[(l+r) div 2]; repeat while t[i]<mid do inc(i); while t[j]>mid do dec(j); if i<=j then begin temp:=t[i];t[i]:=t[j];t[j]:=temp; temp:=s[i];s[i]:=s[j];s[j]:=temp; inc(i);dec(j); end; until i>j; if i<r then qsort(i,r); if j>l then qsort(l,j); end; begin readln(l,n); for i:=1 to n do readln(t[i],s[i]); qsort(1,n); for i:=n-1 downto 1 do if (s[i]-s[i+1])>(t[i+1]-t[i]) then s[i]:=s[i+1]+(t[i+1]-t[i]); t[0]:=0;s[0]:=1;f[0]:=1; for i:=0 to n-1 do begin if (s[i+1]-f[i])<=(t[i+1]-t[i]) then begin temp:=trunc((t[i+1]-t[i]+s[i+1]+f[i])/2); f[i+1]:=s[i+1]; end else begin temp:=f[i]+(t[i+1]-t[i]); f[i+1]:=temp; end; if temp>max then max:=temp; end; if f[n]+(l-t[n])>max then max:=f[n]+(l-t[n]); writeln(max); end.