NOIP2017解题报告
来源:互联网 发布:电子相册制作软件 知乎 编辑:程序博客网 时间:2024/05/22 14:36
1、成绩
(score.cpp/c/pas)
Time Limit: 1 Sec Memory Limit: 256 MB
算法一:
这是一道可以和 A+B Problem 相媲美的题目。
读入三个数后直接输出每个数*对应的百分数之和并去掉小数就行了。
时间复杂度:O(1)
空间复杂度:O(1)
算法一_代码:
1. var
2. a,b,c:longint;
3. begin
4. assign(input, 'score.in');
5. assign(output, 'score.out');
6. reset(input);
7. rewrite(output);
8. read(a,b,c);
9. write(a*0.2+b*0.3+c*0.5:0:0);
10. close(input);
11. close(output);
12. end.
2、图书管理员
(librarian.cpp/c/pas)
Time Limit: 1 Sec Memory Limit: 256 MB
算法一:
又是一道送分题。
因为读入的编号都是不超过 10^7 的正整数,所以我们可以直接把编号用longint 读进来。我们知道一个数mod 10可以截出这个数的最后一位,mod 100可以截出最后两位...那么我们可以用这种方法把每个图书编号的最后与需求码相同位数的最后几位截出来,再去和需求码比较,取符合条件的最小值。
时间复杂度:O(nm)
空间复杂度:O(1)
算法二:
我们还可以用字符串处理这些编号,每次把每个图书编号最后与需求码位数相同的位数截出来,再去和需求码对比。
注意字符串比较大小,先比较长度,再去比较大小。
时间复杂度:O(nm)
空间复杂度:O(1)
算法一_代码:
1. var
2. len,a,b,z:array[0..1001]of longint;
3. n,m,i,j,ans:longint;
4. begin
5. readln(n,m);
6. for i:=1 to n do read(a[i]);
7. for i:=1 to m do
8. begin
9. readln(len[i],b[i]);
10. z[i]:=1;
11. while z[i]<=b[i] do z[i]:=z[i]*10;
12. end;
13. for i:=1 to m do
14. begin
15. ans:=maxlongint;
16. for j:=1 to n do
17. if a[j] mod z[i]=b[i] then
18. if ans>a[j] then ans:=a[j];
19. if ans=maxlongint then writeln(-1)
20. else writeln(ans);
21. end;
22. end.
3、棋盘
(chess.cpp/c/pas)
Time Limit: 1 Sec Memory Limit: 256 MB
算法一:
对于 30%的数据
按照题意直接 dfs,用个常量数组表示方向,可以加个小剪枝,当前的代价
如果已经不小于当前最优解就直接退出。
时间复杂度:O(路径数)
空间复杂度:O(1)
算法二:
Dp,只考虑往下或往右。
我们把 0 看成无色,另外两种颜色为 1 和2。
设状态f[i,j,k]为从当(i,j)的颜色为k时从(1,1)到(i,j)的最小代价。
方程:
如果当前(i,j)有颜色,显然不用魔法更优,所以:
f[i,j,a[i,j]]:=min(f[i-1,j,t],f[i,j-1,t])+dis(t,a[i,j]);当t和a[i,j]相同时dis为0,否则为1
如果当前(i,j)无色,根据题意,不能走无色的格子,所以一定要用魔法,所以:
f[i,j,k]:=min(f[i-1,j,a[i-1,j]]+2+dis(k,a[i-1,j]),f[i,j-1,a[i,j-1]]+2+dis(a[i,j-1],k)));
注意:a[i-1,j]和a[i,j-1]不能为0。dis同上。
时间复杂度:O(n^2)
空间复杂度:O(n^2)
算法三:
上述算法 95...被 ccf 卡掉了一个点...
对于100%的数据
我们可以把这个棋盘看成一个图,那么题目就转化成了从(1,1)到(n,n)的最短路。
思路同 dp,只是现在成了四个方向,跑个SPFA就行了。
时间复杂度:O(kn^2)
空间复杂度:O(kn^2)
算法二_代码:
1. uses math;
2. var
3. f:array[0..101,0..101,1..2]of longint;
4. a:array[0..101,0..101]of longint;
5. n,m,i,j,x,y,z,k,ans:longint;
6. function dis(x,y:longint):longint;
7. begin
8. if x=y then exit(0) else exit(1);
9. end;
10. begin
11. readln(n,m);
12. for i:=1 to m do
13. begin
14. readln(x,y,z);
15. inc(z);
16. a[x,y]:=z;
17. end;
18. for i:=0 to n do
19. for j:=0 to n do
20. for k:=1 to 2 do
21. f[i,j,k]:=maxlongint div 3;
22. f[1,1,a[1,1]]:=0;
23. for i:=1 to n do
24. for j:=1 to n do
25. begin
26. if (i=1)and(j=1) then continue;
27. if a[i,j]=0 then
28. begin
29. for k:=1 to 2 do
30. begin
31. if a[i-1,j]<>0
32. then f[i,j,k]:=min(f[i,j,k],f[i-1,j,a[i-1,j]]+2+dis(a[i-1,j],k));
33. if a[i,j-1]<>0
34. then f[i,j,k]:=min(f[i,j,k],f[i,j-1,a[i,j-1]]+2+dis(a[i,j-1],k));
35. end;
36. end
37. else
38. begin
39. for k:=1 to 2 do
40. f[i,j,a[i,j]]:=min(f[i,j,a[i,j]],f[i-1,j,k]+dis(k,a[i,j]));
41. for k:=1 to 2 do
42. f[i,j,a[i,j]]:=min(f[i,j,a[i,j]],f[i,j-1,k]+dis(k,a[i,j]));
43. end;
44. end;
45. ans:=min(f[n,n,1],f[n,n,2]);
46. if ans=maxlongint div 3 then write(-1) else write(ans);
47. end.
算法三_代码:
1. uses math;
2. const
3. dx:array[1..4]of longint=(0,0,1,-1);
4. dy:array[1..4]of longint=(1,-1,0,0);
5. type
6. arr=record
7. l,r:longint;
8. end;
9. var
10. a:array[0..101,0..101]of longint;
11. dis:array[0..101,0..101,1..2]of longint;
12. b:array[0..101,0..101]of boolean;
13. f:array[0..500001]of arr;
14. n,m,i,j,k,l,r,x,y,z,h,t,ans,zz:longint;
15. function diss(x,y:longint):longint;
16. begin
17. if x<>y then exit(1) else exit(0);
18. end;
19. begin
20. readln(n,m);
21. for i:=1 to m do
22. begin
23. readln(x,y,z);inc(z);a[x,y]:=z;
24. end;
25. for i:=1 to n do
26. for j:=1 to n do
27. for k:=1 to 2 do
28. dis[i,j,k]:=maxlongint >> 1;
29. f[1].l:=1;f[1].r:=1;
30. h:=0; t:=1;
31. dis[1,1,a[1,1]]:=0;
32. while h<=t do
33. begin
34. inc(h);
35. b[f[h].l,f[h].r]:=false;
36. for k:=1 to 4 do
37. begin
38. l:=f[h].l+dx[k]; r:=f[h].r+dy[k];
39. if not (l in [1..n]) or not (r in [1..n]) then continue;
40. if (a[l,r]=0)and(a[f[h].l,f[h].r]=0) then continue;
41. if a[l,r]=0 then
42. for zz:=1 to 2 do
43. begin
44. z:=dis[f[h].l,f[h].r,a[f[h].l,f[h].r]]+2+diss(a[f[h].l,f[h].r],zz);
45. if z<dis[l,r,zz] then
46. begin
47. dis[l,r,zz]:=z;
48. if not b[l,r] then
49. begin
50. inc(t);
51. f[t].l:=l;f[t].r:=r;
52. b[l,r]:=true;
53. end;
54. end;
55. end
56. else
57. for zz:=1 to 2 do
58. begin
59. z:=dis[f[h].l,f[h].r,zz]+diss(a[l,r],zz);
60. if z<dis[l,r,a[l,r]] then
61. begin
62. dis[l,r,a[l,r]]:=z;
63. if not b[l,r] then
64. begin
65. inc(t);
66. f[t].l:=l;f[t].r:=r;
67. b[l,r]:=true;
68. end;
69. end;
70. end;
71. end;
72. end;
73. ans:=min(dis[n,n,1],dis[n,n,2]);
74. if ans=maxlongint >> 1 then write(-1) else write(ans);
75. end.
4、跳房子
(jump.cpp/c/pas)
Time Limit: 2 Sec Memory Limit: 256 MB
算法一:
对于 50%的数据
显然答案具有单调性,那么我们可以用二分答案。
然后对于 check,我们考虑dp来判断得分。
设状态f[i]表示最后一步跳到i的最大的分。
方程:f[i]:=max{f[j]}+s[i];(d-g<=x[i]-x[j]<=d+g)
时间复杂度:O(n^2 log x[n])
空间复杂度:O(n)
算法二:
对于 80%的数据
在算法一的基础上加两个优化。
1.j从后往前枚举,如果当前x[i]-x[j]>r则break。
2.如果当前f[i]已经>=m则直接返回true。
时间复杂度:O(n^2 log x[n])
空间复杂度:O(n)
算法三:
对于 100%的数据。
从算法一可以看出,因为x[i]是递增的,所以符合条件的f[j]肯定是连续的,也就是说f[j]中j的取值范围是个区间,而我们要在这个区间里找个max,用个数据结构维护下就行了。而区间的维护,很自然地就想到了线段树。
时间复杂度:O(n log n log x[n])
空间复杂度:O(4n)
可能是 ccf 没想到会有人用线段树做,线段树能过官方数据。
但是我考场上写挂了,调了1h 都没调出来
算法四:
正解。
用单调队列维护f[j]即可。
因为x[i]是递增的,所以每次符合条件的f[j]的那个区间肯定是往前移动的。每次把比上次多出来符合条件的f[j]加入队列,再把不符合的移出就行了。
最后还要判断一下当前队列的第一个是否符合条件和队列是否为空,因为有可能不能从任何点跳到x[i]。
时间复杂度:O(n log x[n])
空间复杂度:O(n)
算法五:
思路同单调队列,只是换了种数据结构——堆。依旧是每次把符合条件的f[j]加入堆,不符合的移出。
时间复杂度:O(n log n log x[n])
空间复杂度:O(n)
算法二_代码:
1. var
2. a,x,f:array[0..500001]of longint;
3. n,m,k,i,j,l,r,mid,ans:longint;
4. function check(ans:longint):boolean;
5. var
6. i,j,l,r:longint;
7. begin
8. if ans>=k then l:=1 else l:=k-ans;
9. r:=k+ans;
10. for i:=1 to n do
11. begin
12. f[i]:=-233333333;
13. for j:=i-1 downto 0 do
14. begin
15. if x[i]-x[j]>r then break;
16. if (x[i]-x[j]>=l)and(x[i]-x[j]<=r) then
17. if f[j]<>-233333333 then
18. if f[j]>f[i] then f[i]:=f[j];
19. end;
20. if f[i]<>-233333333 then inc(f[i],a[i]);
21. if f[i]>=m then exit(true);
22. end;
23. exit(false);
24. end;
25. begin
26. readln(n,k,m);
27. for i:=1 to n do readln(x[i],a[i]);
28. ans:=-1;
29. l:=0;
30. r:=maxlongint >> 1;
31. while l<=r do
32. begin
33. mid:=(l+r) >> 1;
34. if check(mid) then begin ans:=mid;r:=mid-1 end
35. else l:=mid+1;
36. end;
37. write(ans);
38. end.
算法三_代码:
1. uses math;
2. const
3. p=-233333333;
4. type
5. tree=record
6. l,r:longint;
7. sum:int64;
8. end;
9. var
10. b,x:array[0..500001]of int64;
11. f:array[0..500001]of int64;
12. a:array[0..3000001]of tree;
13. n,m,k,i,j,ans:longint;
14. l,r,mid,sum:int64;
15. procedure build(k,l,r:longint);
16. var
17. mid:longint;
18. begin
19. a[k].l:=l; a[k].r:=r; a[k].sum:=p;
20. if l=r then exit;
21. mid:=(l+r) >> 1;
22. build(k*2,l,mid);
23. build(k*2+1,mid+1,r);
24. end;
25. procedure add(k,l,r,x:longint);
26. var
27. mid:longint;
28. begin
29. if a[k].l=a[k].r then
30. if a[k].l=l then
31. begin
32. a[k].sum:=x;
33. exit;
34. end;
35. mid:=(a[k].l+a[k].r) >> 1;
36. if mid>=l then add(k << 1,l,r,x);
37. if mid<r then add(k << 1+1,l,r,x);
38. a[k].sum:=max(a[k << 1].sum,a[k << 1+1].sum);
39. end;
40. function query(k,l,r:longint):int64;
41. var
42. ans,mid:longint;
43. begin
44. if (a[k].l>=l)and(a[k].r<=r) then exit(a[k].sum);
45. ans:=p;
46. mid:=(a[k].l+a[k].r) >> 1;
47. if mid>=l then ans:=max(ans,query(k << 1,l,r));
48. if mid<r then ans:=max(ans,query(k << 1+1,l,r));
49. exit(ans);
50. end;
51. function check(ans:longint):boolean;
52. var
53. i,j,z,zz:longint;
54. l,r:int64;
55. begin
56. if ans>=k then l:=1 else l:=k-ans;
57. r:=k+ans;
58. build(1,0,n);
59. add(1,0,0,0);
60. z:=0; zz:=-1;
61. for i:=1 to n do
62. begin
63. while x[z]<x[i]-r do inc(z);
64. while x[zz+1]<=x[i]-l do inc(zz);
65. if (z<0)or(zz<0)or(z>zz) then continue;
66. f[i]:=query(1,z,zz);
67. if f[i]<>p then
68. begin
69. inc(f[i],b[i]);
70. add(1,i,i,f[i]);
71. end;
72. if f[i]>=m then exit(true);
73. end;
74. exit(false);
75. end;
76. begin
77. readln(n,k,m);
78. for i:=1 to n do
79. begin
80. readln(x[i],b[i]);
81. if (b[i]>0)and(sum<=m) then inc(sum,b[i]);
82. end;
83. if sum<m then
84. begin
85. writeln(-1);
86. halt;
87. end;
88. ans:=-1;
89. l:=0;
90. r:=x[n];
91. while l<=r do
92. begin
93. mid:=(l+r) >> 1;
94. if check(mid) then begin ans:=mid;r:=mid-1 end
95. else l:=mid+1;
96. end;
97. write(ans);
98. end.
算法四_代码:
1. var
2. x,a,q:array[0..500001]of longint;
3. f:array[0..500001]of int64;
4. n,m,k,i,l,r,mid,ans:longint;
5. function check(z:longint):boolean;
6. var
7. zz,h,t,i,j:longint;
8. begin
9. h:=1;t:=1;
10. q[1]:=0;
11. f[0]:=0;
12. for i:=1 to n do f[i]:=-10000000000;
13. zz:=0;
14. for i:=1 to n do
15. begin
16. while (x[i]-x[zz]>k+z)and(zz<=i) do inc(zz);
17. while (zz<i)and(x[i]-x[zz]>=k-z)and(x[i]-x[zz]<=k+z) do
18. begin
19. while (f[zz]>f[q[t]])and(h<=t) do dec(t);
20. inc(t);
21. q[t]:=zz;
22. inc(zz);
23. end;
24. while (x[i]-x[q[h]]>k+z)and(h<=t) do inc(h);
25. if (h<=t)and(x[i]-x[q[h]]>=k-z)and(x[i]-x[q[h]]<=k+z) then f[i]:=f[q[h]]+a[i];
26. if f[i]>=m then exit(true);
27. end;
28. exit(false);
29. end;
30. begin
31. readln(n,k,m);
32. for i:=1 to n do readln(x[i],a[i]);
33. l:=0;
34. r:=100000;
35. ans:=-1;
36. while l<=r do
37. begin
38. mid:=(l+r) >> 1;
39. if check(mid) then begin ans:=mid;r:=mid-1 end
40. else l:=mid+1;
41. end;
42. writeln(ans);
43. end.
算法五_代码:
1. var
2. x,a,q:array[0..500001]of longint;
3. f:array[0..500001]of int64;
4. n,m,k,i,l,r,mid,ans,len:longint;
5. procedure swap(var x,y:longint);
6. var
7. t:longint;
8. begin
9. t:=x;x:=y;y:=t;
10. end;
11. procedure put(x:longint);
12. var
13. son:longint;
14. begin
15. inc(len);
16. q[len]:=x;
17. son:=len;
18. while (son<>1)and(f[q[son]]>f[q[son >> 1]]) do
19. begin
20. swap(q[son],q[son >> 1]);
21. son:=son >> 1;
22. end;
23. end;
24. procedure get;
25. var
26. fa,son:longint;
27. begin
28. q[1]:=q[len];
29. dec(len);
30. fa:=1;
31. while (fa << 1 <=len)or(fa << 1 +1<=len) do
32. begin
33. if (fa << 1 +1>len)or(f[q[fa << 1 ]]>f[q[fa << 1 +1]]) then son:=fa << 1
34. else son:=fa << 1 +1;
35. if f[q[son]]>f[q[fa]] then
36. begin
37. swap(q[son],q[fa]);
38. fa:=son;
39. end
40. else break;
41. end;
42. end;
43. function check(z:longint):boolean;
44. var
45. zz,i,j,l,r:longint;
46. begin
47. f[0]:=0;
48. for i:=1 to n do
49. begin
50. q[i]:=0;
51. f[i]:=-10000000000;
52. end;
53. len:=0;
54. zz:=0;
55. for i:=1 to n do
56. begin
57. while (x[i]-x[zz]>k+z)and(zz<=i) do inc(zz);
58. while (zz<i)and(x[i]-x[zz]>=k-z)and(x[i]-x[zz]<=k+z) do
59. begin
60. put(zz);
61. inc(zz);
62. end;
63. while (x[i]-x[q[1]]>k+z)and(len>0) do get;
64. if len>0 then f[i]:=f[q[1]]+a[i];
65. if f[i]>=m then exit(true);
66. end;
67. exit(false);
68. end;
69. begin
70. assign(input,'jump.in');
71. assign(output,'jump.out');
72. reset(input);
73. rewrite(output);
74. readln(n,k,m);
75. for i:=1 to n do readln(x[i],a[i]);
76. l:=0;
77. r:=x[n];
78. ans:=-1;
79. while l<=r do
80. begin
81. mid:=(l+r) >> 1;
82. if check(mid) then begin ans:=mid;r:=mid-1 end
83. else l:=mid+1;
84. end;
85. writeln(ans);
86. close(input);
87. close(output);
88. end.
- noip2017解题报告题解
- NOIP2017解题报告
- NOIP2017解题报告
- NOIP2017解题报告
- NOIP2017提高组解题报告
- [NOIP2017]提高组解题报告
- NOIP2017提高组解题报告
- NOIP2017普及组解题报告
- NOIP2017普及组复赛解题报告
- 正睿OI noip2017冲刺 第一次考试T2 解题报告
- 解题报告
- 解题报告
- 解题报告
- 解题报告
- 解题报告
- 解题报告
- 解题报告
- NOIP2017 宝藏 题解报告【状压dp】
- 单目运算符前++与后++的重载
- 虚拟机 grub error: unknown filesystem错误解决办法
- JAVA循环结构
- sendkeys模拟键盘QTP
- iOS开发之KVC和KVO原理解析和实例分析
- NOIP2017解题报告
- 移动端常用的meta属性
- python基本正则表达式
- 设计模式(十六)——迭代器模式
- CSS 常遇问题
- 关于项目中的日志文档
- MyBatis 插件之拦截器(Interceptor)实现原理
- 生成图标
- CentOS下安装Redis