现在的位置: 首页 > 综合 > 正文

俄罗斯方块 tetris

2018年01月15日 ⁄ 综合 ⁄ 共 3484字 ⁄ 字号 评论关闭

俄罗斯方块 tetris

【题意】

俄罗斯方块游戏,在一个宽度为n高度为h的矩阵中进行,给定初始状态,每次给定一个形状的方块,将它放到最靠左进行最少旋转次数可不出现“洞”(就是说同一列方块之间有缝隙)且加入后最高高度不超过h的位置,并输出这个位置,跟一般的俄罗斯方块一样,一行满了便会消行

各种编号对应的方块

0

**

*

*

1

**

 *

 *

2

 **

**

3

**

 **

4

***

 *

5

**

**

6

****

【输入】

第一行n、m、h(皆小于等于100000)

接下来m行每行一个数字表示加入的方块的形状

【输出】

对于每次加入输出其位置

十分麻烦的题

首先需要一个函数(这里是could)来判断某位置是否能放入一个某形状的方块

然后用线段树来维护,维护两个值,区间内高度最低值和用一个7位2进制数表示的以区间内的点为起点每种形状是否能放入

那么对于每次插入,查询最靠左的点,并更新有关的最多七个点,总查询并更新复杂度为mlogn

对于消行,每次重建线段树即可,消行次数最多为4*m/n,每次重建为nlogn,所以总重建复杂度为mlogn

虽然常数比较大,但这个复杂度对于时限3s的本题还是很轻松的

program tetris;
const
  plus:array [0..6,1..4,0..3] of longint
  =(
   ((3,1,0,0),(1,1,2,0),(1,3,0,0),(2,1,1,0)),
   ((1,3,0,0),(1,1,2,0),(3,1,0,0),(2,1,1,0)),
   ((1,2,1,0),(2,2,0,0),(0,0,0,0),(0,0,0,0)),
   ((1,2,1,0),(2,2,0,0),(0,0,0,0),(0,0,0,0)),
   ((1,2,1,0),(1,3,0,0),(1,2,1,0),(3,1,0,0)),
   ((2,2,0,0),(0,0,0,0),(0,0,0,0),(0,0,0,0)),
   ((1,1,1,1),(4,0,0,0),(0,0,0,0),(0,0,0,0))
   );
  dif:array [0..6] of longint=(4,4,2,2,4,1,2);
  long:array [0..6,1..4] of longint
  =(
   (2,        3,        2,        3        ),
   (2,        3,        2,        3        ),
   (3,        2,        0,        0        ),
   (3,        2,        0,        0        ),
   (3,        2,        3,        2        ),
   (2,        0,        0,        0        ),
   (4,        1,        0,        0        )
   );
  need:array [0..6,1..4,0..2] of longint
  =(
   ((-2,9,9), (0,1,9),  (0,9,9),  (0,0,9)  ),
   ((2,9,9),  (0,0,9),  (0,9,9),  (-1,0,9) ),
   ((0,-1,9), (1,9,9),  (9,9,9),  (9,9,9)  ),
   ((1,0,9),  (-1,9,9), (9,9,9),  (9,9,9)  ),
   ((1,-1,9), (1,9,9),  (0,0,9),  (-1,9,9) ),
   ((0,9,9),  (9,9,9),  (9,9,9),  (9,9,9)  ),
   ((0,0,0),  (9,9,9),  (9,9,9),  (9,9,9)  )
   );
var
  minn,tot,h,n,m,i,j,k,t:longint;
  high:array [0..100001] of longint;
  min,left,right,status:array [0..200001] of longint;

function could (now,form:longint):longint;
var
  ok:boolean;
  i,j,k:longint;
begin
  for i:=1 to dif[form] do
    begin
      if (high[now]+plus[form,i,0]>h)or(now+long[form,i]-1>n) then continue;
      ok:=true;
      for j:=0 to long[form,i]-2 do
        if (high[now+j]-high[now+j+1]<>need[form,i,j])
        or(high[now+j+1]+plus[form,i,j+1]>h)
        then
          begin
            ok:=false;
            break
          end;
      if ok then exit(i);
    end;
  exit(0);
end;

procedure change (who,l,r,now:longint);
var
  i:longint;
begin
  if l=r then
    begin
      min[now]:=high[who];
      status[now]:=0;
      for i:=0 to 6 do
        if could(who,i)<>0 then status[now]:=status[now] or (1 shl i);
      exit;
    end;
  if who<=(l+r) div 2 then change(who,l,(l+r) div 2,left[now])
                      else change(who,(l+r) div 2+1,r,right[now]);
  status[now]:=status[left[now]] or status[right[now]];
  if min[left[now]]<min[right[now]] then min[now]:=min[left[now]]
                                    else min[now]:=min[right[now]];
end;

procedure quick (s,e,now:longint);
var
  i,mid:longint;
begin
  if s=e then
    begin
      left[now]:=0;
      right[now]:=0;
      status[now]:=0;
      min[now]:=high[s];
      for i:=0 to 6 do
        if could(s,i)<>0 then status[now]:=status[now] or (1 shl i);
      exit;
    end;
  mid:=(s+e) div 2;
  inc(tot);
  left[now]:=tot;
  inc(tot);
  right[now]:=tot;
  quick(s,mid,left[now]);
  quick(mid+1,e,right[now]);
  status[now]:=status[left[now]] or status[right[now]];
  if min[left[now]]<min[right[now]] then min[now]:=min[left[now]]
                                    else min[now]:=min[right[now]];
end;

procedure build ;
begin
  tot:=0;
  quick(1,n,0);
end;

function find (form,l,r,now:longint):longint;inline;
begin
  if l=r then exit(l);
  if status[left[now]] or (1 shl form)=status[left[now]] then
    exit(find(form,l,(l+r) div 2,left[now]))
                                                          else
    exit(find(form,(l+r) div 2+1,r,right[now]));
end;

procedure update (now,form,status:longint);
var
  i,k:longint;
begin
  for i:=0 to long[form,status]-1 do
    high[now+i]:=high[now+i]+plus[form,status,i];
  for i:=0 to long[form,status]-1 do
    change(now+i,1,n,0);
  for i:=1 to 3 do
    if now-i>0 then
      change(now-i,1,n,0);
  if min[0]<>0 then
    begin
      for i:=1 to n do
        high[i]:=high[i]-min[0];
      build;
    end;
end;

begin
  assign(input,'tetris.in');
  reset(input);
  assign(output,'tetris.out');
  rewrite(output);
  read(n,m,h);
  minn:=maxlongint;
  for i:=1 to n do
    begin
      read(high[i]);
      if high[i]<minn then minn:=high[i];
    end;
  for i:=1 to n do
    high[i]:=high[i]-minn;
  build;
  for i:=1 to m do
    begin
      read(t);
      j:=find(t,1,n,0);
      writeln(j-1);
      k:=could(j,t);
      update(j,t,k);
    end;
  close(input);
  close(output);
end.

【上篇】
【下篇】

抱歉!评论已关闭.