題目大意
俄羅斯方塊。
有三種塊,每種塊都可以旋轉:
有四種操作,可以將當前塊左移(a),右移(d),旋轉(w),下降(d)。
其實還有一種操作p,表示不動。
塊會自然下降。
每個塊的特殊塊(綠點)開始時在(4,9)
如果當前操作不合法,那麼忽略。
如果一排被填滿了,那麼刪掉這行,上面的行就會掉下來,分數++。
求最終的分數。
題解
好久沒做模擬題了~~
首先要對每種塊的每個狀態打表,以特殊塊爲(0,0),記錄每個位置的被佔據情況。
再寫個函數叫check,用來判斷當前這種塊以當前的狀態,是不是和圖衝突。
如果這個塊再向下降就不合法了,那麼就停住,寫個函數叫set_down,把這個塊放在圖中。
最後一個函數叫做clear,就是把一行滿的刪掉。這裏有一個小技巧,從題解中學到的,就是隻有碰到一行不是滿的,就把它從頭加入,最後把除了這幾行之外的全memset成0就可以了。
還有一個有意思的技巧,就是在switch-case語句中,爲什麼可以寫這種條件語句呢?
switch(oper[i]){
case 'w':
check(kind[m],(t+1)%tot[kind[m]],x,y)&&(t=(t+1)%tot[kind[m]]);
break;
case 'a':
check(kind[m],t,x,y-1)&&y--;
break;
case 's':
check(kind[m],t,x-1,y)&&x--;
break;
case 'd':
check(kind[m],t,x,y+1)&&y++;
break;
}
這是因爲&&具有斷路性(不知道是不是這個詞),就是某一個條件不滿足時,後面的語句都不會執行,於是如果check不通過,右面的++,–就不會執行。
#include<cstdio>
#include<cstring>
bool vis[4][4][4][4];//類型,特殊塊周圍的被佔據情況
int tot[]={1,2,4},kind[1005],ans=0;
bool mp[20][20];
char oper[1005];
bool check(int k,int t,int x,int y){
if(x>12||x<1||y>9||y<1) return false;
for(int i=0;i<4;i++)
for(int j=0;j<4;j++)
if((mp[x+i][y+j]||x+i>12||y+j>9)&&vis[k][t][i][j]) return false;
return true;
}
void set_down(int k,int t,int x,int y){
for(int i=0;i<4;i++){
for(int j=0;j<4;j++){
if(x+i>12||y+j>9) continue;
mp[x+i][y+j]|=vis[k][t][i][j];
}
}
}
void print(){
for(int i=12;i>0;i--){
for(int j=1;j<=9;j++)
printf("%d",mp[i][j]);
puts("");
}
puts("");
}
void clear(){
int tmp=1;
for(int i=1;i<=12;i++){
for(int j=1;j<=9;j++){
if(!mp[i][j]){
for(int w=1;w<=9;w++)
mp[tmp][w]=mp[i][w];
tmp++;
break;
}
if(j==9) ans++;
}
}
for(int i=tmp;i<=12;i++)
memset(mp[i],0,sizeof(mp[i]));
}
void work(){
for(int t=0,m=0,i=0,x=9,y=4;i<strlen(oper);i++){
switch(oper[i]){
case 'w':
check(kind[m],(t+1)%tot[kind[m]],x,y)&&(t=(t+1)%tot[kind[m]]);
break;
case 'a':
check(kind[m],t,x,y-1)&&y--;
break;
case 's':
check(kind[m],t,x-1,y)&&x--;
break;
case 'd':
check(kind[m],t,x,y+1)&&y++;
break;
}
if(!check(kind[m],t,x-1,y)){
set_down(kind[m],t,x,y);
clear();
m++;t=0;x=9;y=4;
}else x--;
// print();
// puts("");
}
}
void Init(){
vis[0][0][0][0]=vis[0][0][0][1]=vis[0][0][1][0]=vis[0][0][1][1]=1;
vis[1][0][0][0]=vis[1][0][1][0]=vis[1][0][2][0]=vis[1][0][3][0]=1;
vis[1][1][0][0]=vis[1][1][0][1]=vis[1][1][0][2]=vis[1][1][0][3]=1;
vis[2][0][0][0]=vis[2][0][0][1]=vis[2][0][0][2]=vis[2][0][1][0]=1;
vis[2][1][0][0]=vis[2][1][1][0]=vis[2][1][2][0]=vis[2][1][2][1]=1;
vis[2][2][1][0]=vis[2][2][1][1]=vis[2][2][1][2]=vis[2][2][0][2]=1;
vis[2][3][0][0]=vis[2][3][0][1]=vis[2][3][1][1]=vis[2][3][2][1]=1;
}
int solve(){
memset(mp,0,sizeof(mp));
int n;
scanf("%d",&n);
scanf("%s",oper);
ans=0;
for(int i=0;i<n;i++)
scanf("%d",&kind[i]);
work();
return ans;
}
int main(){
Init();
int T;
scanf("%d",&T);
for(int i=1;i<=T;i++)
printf("Case %d: %d\n",i,solve());
return 0;
}