[noip2011 d1t3] Mayan游戏

无脑码农题==

烦的是很多细节,把几个主要过程分开写,化整为零会清楚很多

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<cmath>
  4 #include<algorithm>
  5 using namespace std;
  6 #define mxcol 12
  7 int map[10][10];
  8 int goal;
  9 struct data{
 10     int x,y,w;
 11 }ans[10];
 12 int read(){
 13     int x=0;
 14     char ch=getchar();
 15     while (ch<'0'||ch>'9') ch=getchar();
 16     while (ch>='0'&&ch<='9'){
 17         x=x*10+ch-'0';
 18         ch=getchar();
 19     }
 20     return x;
 21 }
 22 bool empty(){
 23     for (int i=0;i<5;i++)
 24       for (int j=0;j<7;j++)
 25         if (map[i][j]) return 0;
 26     return 1;
 27 }
 28 void DROP(){
 29     int time[10][10];
 30     memset(time,-1,sizeof(time));
 31     for (int x=0;x<5;x++){
 32         int num=0;
 33         for (int y=0;y<7;y++)
 34           if (map[x][y])
 35             time[x][num++]=y;
 36     }
 37     for(int x=0;x<5;x++)
 38       for (int y=0;y<7;y++)
 39         map[x][y]=time[x][y]==-1?0:map[x][time[x][y]];
 40 }
 41 bool CLEAR(){
 42     bool flag=0;
 43     //
 44     for (int i=0;i<3;i++)
 45       for (int j=0;j<7;j++)
 46         if (map[i][j]){
 47             int x;
 48             for (x=i;x+1<5&&map[i][j]==map[x+1][j];x++);
 49             if (x-i>=2){
 50                 int nx;
 51                 for (nx=i;nx<=x;nx++){
 52                     int up=j,down=j;
 53                     while (up+1<7&&map[nx][up+1]==map[i][j]) up++;
 54                     while (down-1>=0&&map[nx][down-1]==map[i][j]) down--;
 55                     if (up-down>=2){
 56                         for (int ny=down;ny<=up;ny++)
 57                           map[nx][ny]=0;
 58                     }
 59                 }
 60                 for (nx=i;nx<=x;nx++)
 61                   map[nx][j]=0;
 62                 flag=1;
 63             }
 64         }
 65     //
 66     for (int i=0;i<5;i++)
 67       for (int j=0;j<5;j++)
 68         if (map[i][j]){
 69             int y;
 70             for (y=j;y+1<7&&map[i][y+1]==map[i][j];y++);
 71             if (y-j>=2){
 72                 int ny;
 73                 for (ny=j;ny<=y;ny++){
 74                     int left=i,right=i;
 75                     while (left>0&&map[left-1][ny]==map[i][j]) left--;
 76                     while (right+1<7&&map[right+1][ny]==map[i][j]) right++;
 77                     if (right-left>=2){
 78                         for (int nx=left;nx<=right;nx++)
 79                         map[nx][ny]=0;
 80                     }
 81                 }
 82                 for (ny=j;ny<=y;ny++)
 83                   map[i][ny]=0;
 84                 flag=1;
 85             }
 86         }
 87     return flag;
 88 }
 89 void dfs(int step){
 90     if (step>goal){
 91         if (empty()){//判断游戏结束 
 92             for (int i=1;i<=goal;i++)
 93               if (ans[i].w)
 94                 printf("%d %d -1\n",ans[i].x+1,ans[i].y);
 95               else 
 96                 printf("%d %d 1\n",ans[i].x,ans[i].y); 
 97             exit(0);
 98         }
 99         return;
100     }
101     
102     int time[mxcol];
103     memset(time,0,sizeof(time));
104     for (int i=0;i<5;i++)
105       for (int j=0;j<7;j++)
106         time[map[i][j]]++;
107     for (int i=1;i<=10;i++)
108       if (time[i]!=0&&time[i]<3) return;//剪枝:当某种颜色块数小于3时必然无解 
109     
110     for (int x=0;x<4;x++)//优先向右换;按字典序枚举 
111       for (int y=0;y<7;y++)
112         if (map[x][y]!=map[x+1][y]){//两方块颜色不同时才交换 
113              ans[step].x=x,ans[step].y=y;
114              ans[step].w=!map[x][y];//枚举的时候是从左往右,但也可能左边空右边有方块,此时标记将右边的方块向左移动 
115              int tmp[10][10];
116              memcpy(tmp,map,sizeof(tmp));
117              swap(map[x][y],map[x+1][y]);
118              
119              DROP();
120              while (CLEAR()) DROP();
121              //两个主要过程:上面的方块掉落;合法的方块消去 
122              dfs(step+1);
123              
124              ans[step].x=0,ans[step].y=0;
125              ans[step].w=0;
126              memcpy(map,tmp,sizeof(map));
127         }
128 }
129 int main(){
130     goal=read();
131     memset(map,0,sizeof(map));
132     for (int i=0;i<5;i++){
133         for (int j=0;;j++){
134             int u=read();
135             if (!u) break;
136             map[i][j]=u;
137         }
138     }
139     dfs(1);
140     printf("-1\n");
141     return 0;
142 } 
View Code

 

posted @ 2017-08-23 22:06  Vincent_hwh  阅读(145)  评论(0编辑  收藏  举报