2016.08.15【初中部 NOIP提高组 】模拟赛C题解
来源:互联网 发布:澳洲新闻软件下载 编辑:程序博客网 时间:2024/06/06 08:31
T1:
第一题不讲了,小学数学,一年级,没A的自觉吃屎。直接上代码
function pd(x1,y1,z1,x2,y2,z2:longint):longint;begin if x1*3600+y1*60+z1<=x2*3600+y2*60+z2 then exit((x2*3600+y2*60+z2)-(x1*3600+y1*60+z1)) else exit(86400-(x1*3600+y1*60+z1)+(x2*3600+y2*60+z2));end;
procedure zz(x,y,z,t:longint);var sum,w1,w2,w3:longint;begin sum:=x*3600+y*60+z+t; if sum>=86400 then dec(sum,86400); w1:=sum div 3600; dec(sum,w1*3600); w2:=sum div 60; dec(sum,w2*60); if w1<10 then write('0',w1,':') else write(w1,':'); if w2<10 then write('0',w2,':') else write(w2,':'); if sum<10 then write('0',sum) else write(sum); writeln;end;
T2:
第二题考试的时候 ,读错题目,以为是任意连续3个都不相同,结果当然是爆零。正解目测就知道是DP,因为递归超时的题目,又可以划分阶段,一般都是DP。把前i个数划分阶段。用f[i,j]表示前i个数,当前放在j车站的最小值。(1<=i<=n)(1<=j<=3)然后很明显方程就是其余2个最小的再加上当前a[i,j]
f[i,j]:=min(f[i,j],f[i,j])+a[i,j]。前面j的值为不等于j的另外2个值。
for i:=1 to n do for j:=1 to 3 do if j=1 then f[i,j]:=min(f[i-1,2],f[i-1,3])+a[i,j] else if j=2 then f[i,j]:=min(f[i-1,1],f[i-1,3])+a[i,j] else f[i,j]:=min(f[i-1,1],f[i-1,2])+a[i,j];T3:
这道题是4题中最难的。很明显可以发现,只要判断一下回路和没有回路的路径即可。例如:
例如这个图,很明显可以发现3,4,5构成了环路,可是怎么在接近线性的时间来判断环路呢?
说到这个,我们很容易想到了拓扑排序,把没有爸爸的节点给删掉,于是,我们就可以用O(2n)的方法,一个枚举哪个没有爸爸,一个对于没有爸爸的这个点按照它对应到达的城市进行删除。删除最多为n,枚举也是n,所以为O(2n)
用这个例子来说,一开始扫到了没有爸爸的1,按照顺序,删掉1,然后把c[1](表示1这个位置爸爸节点的个数)赋值为-1,然后它对应c[b[i]]也就是对应的城市-1.然后到2继续扫,我这里是扫到了1个就对他进行循环+删除。
很明显,最后c[i]的值大于0的,一定会是回路,因为回路互为父亲。
for i:=1 to n do if c[i]=0 then begin k:=i; while c[k]=0 do//如果当前的值没有父亲 begin c[k]:=-1;//把他赋值为-1,意思为不是回路 dec(c[b[k]]);//对应那个城市他父亲个数的值减一 k:=b[k];//继续判断,将当前指针指向对应城市 end; end;然后我们就可以判断他的回路了。很明显,按照他的走。如果碰到已经碰到过的路,则把整个走过的回路赋值为它刚才一共走的值,这样在第二次循环碰到是这个回路中的路就不用再次模拟了。
fillchar(h,sizeof(h),255);//h[i]表示第i个位置是回路的值。因为输入的值可能为0,所以全部为-1(fillchar255就是1) for i:=1 to n do if (c[i]>=1)and(h[i]=-1) then//判断当前是否为回路并且当前是否判断过回路 begin k:=i; ans:=0; while (k<>i)or(ans=0) do begin inc(ans,a[k]); if k=b[k] then break;//注意有坑爹数据,加上这个判断,如果自己和自己构成回路就直接退出,否则会一直循环。 k:=b[k]; end;//这个就是按照回路来走,并且累加它的和 k:=i; while (k<>i)or(h[k]=-1) do begin h[k]:=ans; k:=b[k]; end;//把刚才搞过的回路都赋值为ans end;最后一个步骤就是输出了。输出的时候,如果当前为回路,就直接输出,否则就要计算了。从当前点走,直到碰到一个回路,就输出原先当前点到第一个回路的值再加上这个回路的数值即可。有个优化,懒得加了。例如有1,2,3。3这个位置是回路,那么你算了1->3的路径,倒过来,就像递归一样(当然可以用递归实现)路径压缩,返回2->3的值了。请选手自行修改
for i:=1 to n do if h[i]>0 then writeln(h[i]) else begin ans:=a[i]; k:=b[i]; while (h[k]=-1) do begin inc(ans,a[k]); k:=b[k]; end; writeln(ans+h[k]); end;T4:
bfs,利用了最先找到的值一定为最优的特点,注意细节,太水了,做过产生数的都会做。上代码。
第一种情况:
for i:=1 to length(s)-1 do for j:=i+1 to length(s) do begin str(now,ss); 交换两个位置的值 val(ss,p); if (bz[p]=0)and(p<>n) then begin tail:=tail mod 100000+1; d[tail,0]:=d[head,0]+1; d[tail,1]:=p; bz[p]:=d[tail,0]; end;//判断入队 end;第二种情况:
for i:=1 to length(s) do begin str(now,ss); delete(ss,i,1); val(ss,p); if (bz[p]=0)and(p<>n) then begin tail:=tail mod 100000+1; d[tail,0]:=d[head,0]+1; d[tail,1]:=p; bz[p]:=d[tail,0]; end; end;第三种情况:
for i:=1 to length(s)-1 do for k:='1' to '9' do begin ss:=s; if (ss[i]<k)and(k<ss[i+1]) then begin str(now,ss); insert(k,ss,i+1); val(ss,p); if (bz[p]=0)and(p<>n)and(length(ss)<=length(jj)) then begin tail:=tail mod 100000+1; d[tail,0]:=d[head,0]+1; d[tail,1]:=p; bz[p]:=d[tail,0]; end; end; end;代码码的有点丑,有点麻烦,比赛赶时间,随便打了一下,请自行更改。
总结:
码的智障,有人用百度优先搜索。第一题水过,第二题看错题目,第三题没想到,不过想到拓扑,但是想到超时就止步了。最后一道题粗心码错了
估分:100+100+0+100
得分:100+0+0+40
Orz接近最后。下次加油
- 2016.08.15【初中部 NOIP提高组 】模拟赛C题解
- 2016.08.15【初中部 NOIP提高组 】模拟赛C题解
- 2016.08.15【初中部 NOIP提高组 】模拟赛C题解
- 2016.08.11【初中部 NOIP提高组 】模拟赛C题解
- 2016.08.11【初中部 NOIP提高组 】模拟赛C题解
- 2016.08.12【初中部 NOIP提高组 】模拟赛C题解
- 2016.08.12【初中部 NOIP提高组 】模拟赛C题解
- 2016.08.13【初中部 NOIP提高组 】模拟赛C题解
- 2016.08.13【初中部 NOIP提高组 】模拟赛C题解
- 2016.08.13【初中部 NOIP提高组 】模拟赛C题解
- 2016.08.12【初中部 NOIP提高组 】模拟赛C题解
- 2016.08.14【初中部 NOIP提高组 】模拟赛C题解
- 2016.08.14【初中部 NOIP提高组 】模拟赛C题解
- 2016.08.11【初中部 NOIP提高组 】模拟赛C题解
- 2016.08.14【初中部 NOIP提高组 】模拟赛C题解
- 2016.08.16【初中部 NOIP提高组 】模拟赛C题解
- 2016.08.16【初中部 NOIP提高组 】模拟赛C题解
- 2016.08.17【初中部 NOIP提高组 】模拟赛C题解
- ARM_Linux_NOTE_1
- {模板}SPFA
- window10 Arduino Mega 2560 插上电脑找不到端口
- 从Instant-Run出发,谈谈Android上的热修复
- HDU 2594 Simpsons’ Hidden Talents(kmp)
- 2016.08.15【初中部 NOIP提高组 】模拟赛C题解
- C++ 错题
- 验证数字的------正则表达式集
- 文章标题
- 2016-8-15 第一次训练 代码
- POJ 3304 直线和线段相交
- ARM_Linux_NOTE_2
- Southern Subregion Problem H. Password Service
- shell学习记录