NOIP2011解题报告-Day1
题目:
https://files.cnblogs.com/lijianlin1995/NOIP2011%E6%8F%90%E9%AB%98%E7%BB%84Day1.pdf
CLJ神犇的NOIP题解应该是最广为流的,但是神犇就是神犇,追求复杂度,方法很高端。所以我写一点能过就行的算法。RQNOJ提交通过了。
铺地毯
第一感觉二维线段树,发现只查询一个点,可以朴素。如果halt要注意文件操作。
1 type Tdt=record
2 x,y,xl,yl:longint;
3 end;
4 var dt:array[1..10000] of Tdt;
5 i,color,n,x,y:longint;
6 begin
7 readln(n);
8 for i:=1 to n do
9 with dt[i] do
10 readln(x,y,xl,yl);
11 readln(x,y);
12 color:=-1;
13 for i:=n downto 1 do
14 if (x>=dt[i].x)and(x<=dt[i].x+dt[i].xl)and
15 (y>=dt[i].y)and(y<=dt[i].y+dt[i].yl)
16 then begin
17 color:=i;
18 break;
19 end;
20 writeln(color);
21 end.
旅馆
考试的时候写的O(n^2)的算法,枚举左右端点,维护区间最小值,得分很低。
把两个人的住宿位置看做一个闭区间的左右端点。一个合法的区间要求:
I:含有一个点i满足ok[i]=1
II:color[l]=color[r]
求出合法的区间数即为答案。
维护前缀和,count[i][j]为前1..i颜色j的数量,用指针f记录最后出现ok[i]=1的i。如果一个区间可以由靠左的ok[i]满足,一定可以由区间内靠右的ok[i]满足,不妨让最靠右的ok[i]满足。从1到n枚举区间右端点。通过前缀和计算左端点的方案数。
1.ok[i]=1 可以在i喝咖啡,右边的人可以住的位置是count[i-1][color[i]],f更改为i;(条件I被右端点满足)
2.ok[i]=0 在f喝咖啡,inc(ans,count[f][color[i]]);(条件II被f满足)
1 program hotel;
2 const maxn=200000;
3 var color:array[0..maxn] of byte;
4 ok:array[0..maxn] of boolean;
5 n,p,k,i,f,t:longint;
6 count:array[0..maxn,0..50] of longint;
7 ans:int64=0;
8 begin
9 fillchar(count,sizeof(count),0);
10 readln(n,k,p);f:=0;
11 for i:=1 to n do
12 begin
13 readln(color[i],t);
14 if t<=p then ok[i]:=true
15 else ok[i]:=false;
16 count[i]:=count[i-1];
17 inc(count[i][color[i]]);
18 end;
19 for i:=1 to n do
20 begin
21 if ok[i] then f:=i-1;
22 inc(ans,count[f][color[i]]);
23 if ok[i] then inc(f);
24 end;
25 writeln(ans);
26 end.
Mayan游戏
DFS,复杂度5*7^5=52521875不大,加上下落和清除,期望得分30—100。要注意横纵坐标和行列的关系。几个剪枝和要注意的问题:
1.如果一个方块左边有方块,那左边的方块右移比右边的方块左移优。
2.方块移动以后没有处理下落会WA40
3.读数据出问题,如果一行有7个方块,会有8个数字(最后一个是0),WA20
4.处理消除后的方块下落时下标越界。
5.忘记向左移动 WA60
2的处理写疵了,索性用了消除后的下落过程。
考试跟KAC大神同考场,考完大神叹息“我写了3KB”
1 program mayan; 2 TYPE Tmap=array[0..4,0..7] of shortint; 3 var n,i,j,step:longint; 4 a:Tmap; 5 t:shortint; 6 x,y,g:array[1..5] of integer; 7 procedure swap(var a,b:shortint); 8 var t:shortint;begin t:=a;a:=b;b:=t;end; 9 procedure print; 10 var i:longint; 11 begin 12 for i:=1 to step do 13 writeln(x[i],' ',y[i],' ',g[i]); 14 halt; 15 end; 16 function clean(var map:Tmap):boolean; 17 var i,j,k:integer; 18 finish:boolean; 19 f:array[0..4,0..6] of boolean; 20 begin 21 clean:=true; 22 fillchar(f,sizeof(f),false); 23 for i:=0 to 4 do 24 for j:=0 to 6 do 25 if map[i][j]<>0 then 26 begin 27 if(i in [1..3])and 28 (map[i][j]=map[i-1][j])and 29 (map[i][j]=map[i+1][j]) 30 then begin 31 f[i][j]:=true; 32 f[i-1][j]:=true; 33 f[i+1][j]:=true; 34 end; 35 if(j in [1..5])and 36 (map[i][j]=map[i][j+1])and 37 (map[i][j]=map[i][j-1]) 38 then begin 39 f[i][j]:=true; 40 f[i][j+1]:=true; 41 f[i][j-1]:=true; 42 end; 43 end; 44 for i:=0 to 4 do 45 for j:=6 downto 0 do 46 if f[i][j] then 47 begin 48 clean:=false; 49 map[i][j]:=0; 50 end; 51 end; 52 procedure fall(var map:Tmap); 53 var i,j,k:integer; 54 begin 55 for i:=0 to 4 do 56 for j:=1 to 6 do 57 if(map[i][j]<>0)and(map[i][j-1]=0) 58 then begin 59 k:=j; 60 while(k>0)and(map[i][k-1]=0)do dec(k); 61 map[i][k]:=map[i][j];map[i][j]:=0; 62 end; 63 end; 64 function finish(map:Tmap):boolean; 65 var i,j:longint; 66 begin 67 for i:=0 to 4 do 68 for j:=0 to 6 do 69 if map[i][j]<>0 70 then exit(false); 71 exit(true); 72 end; 73 procedure DFS(map:Tmap); 74 var i,j,k:integer; 75 begin 76 if step<>0 then swap(map[x[step]][y[step]],map[x[step]+g[step]][y[step]]); 77 repeat fall(map) until clean(map); 78 if step=n then if finish(map)then print 79 else exit; 80 for i:=0 to 4 do 81 for j:=0 to 6 do 82 begin 83 if map[i][j]<>0 84 then begin 85 inc(step); 86 if(i>0)and(map[i-1][j]=0) 87 then begin 88 x[step]:=i; 89 y[step]:=j; 90 g[step]:=-1; 91 DFS(map); 92 end; 93 if(i<4) 94 then begin 95 x[step]:=i; 96 y[step]:=j; 97 g[step]:=1; 98 DFS(map); 99 end; 100 dec(step); 101 end; 102 end; 103 end; 104 begin 105 readln(n);step:=0; 106 for i:=0 to 4 do 107 begin 108 t:=-1; 109 repeat 110 inc(t); 111 read(a[i][t]); 112 until a[i][t]=0; 113 end; 114 DFS(a); 115 writeln('-1'); 116 end.