赛克oj 1540 开心消消乐(并查集、模拟、回溯)

赛氪OJ-专注于算法竞赛的在线评测系统 (saikr.com)

题目描述

近来,小明的班上风靡着一款名为“开心消消乐”的游戏,为了成为大家眼中的超人,小明开始疯狂研究这款游戏的玩法。

游戏的场景是一个𝑛×𝑚n×m的正方形矩阵,其中有着4种不同形状的方块,玩家要做的就是尽可能多的消除掉其中的方块。

在游戏中,各个方块和上下左右四个方向的相邻位置上形状相同的方块共同构成了一个又一个连通块,玩家选中一个位置后,若该位置所在连通块的方块总数不小于3,那么就可以消除掉这一连通块,得到分数。需要注意的是,游戏存在着重力机制,在机制作用下,每次消除后腾空的方块会下落。

显然,由于重力机制的影响,消除顺序会影响到游戏的最终得分,现在给定游戏矩阵,若简单记每个方块为1分,请试着找出最大的得分。

输入

输入格式:

  • 第一行输入两个数n、m,表示矩阵大小。
  • 之后n行,每行m个数,表示方块矩阵。每个数可能为1、2、3、4,分别对应一种形状。

输出

输出格式:

  • 输出一行一个数,表示最大得分。

思路

模拟题。用回溯来进行消除顺序的确定,用并查集消除某一块,主要是注意细节。

  1 #define IO std::ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)
  2 #define bug(x) cout<<#x<<" is "<<x<<endl
  3 #include <bits/stdc++.h>
  4 #define iter ::iterator
  5 using namespace  std;
  6 typedef long long ll;
  7 typedef pair<int,int>P;
  8 #define pb push_back
  9 #define mk make_pair
 10 #define se second
 11 #define fi first
 12 #define rs o*2+1
 13 #define ls o*2
 14 
 15 int n,m,ans;
 16 
 17 int a[10][10];
 18 
 19 int fa[50];
 20 
 21 int find(int x){
 22     return fa[x]==x?x:fa[x]=find(fa[x]);
 23 }
 24 int check(int x,int y){
 25     if(x<1||x>n||y<1||y>m||!a[x][y])return 0;
 26     return 1;
 27 }
 28 
 29 int dx[4]={0,0,1,-1};
 30 int dy[4]={1,-1,0,0};
 31 
 32 int flag[10][10];
 33 
 34 int cnt[50];
 35 
 36 void gao(int h){
 37     int res=0;
 38     //printf("h=%d\n",h);
 39     for(int i=1;i<=n;i++){
 40         for(int j=1;j<=m;j++){
 41             if(!a[i][j])res++;
 42             //printf("%d ",a[i][j]);
 43         }
 44         //printf("\n");
 45     }
 46     //printf("\n");
 47     ans=max(ans,res);
 48     if(h==9){
 49         return;
 50     }
 51     for(int i=1;i<=n*m;i++)fa[i]=i,cnt[i]=0;
 52     
 53     for(int i=1;i<=n;i++){
 54         for(int j=1;j<=m;j++){
 55             for(int k=0;k<4;k++){
 56                 if(!a[i][j])continue;
 57 
 58                 int x=i+dx[k];
 59                 int y=j+dy[k];
 60                 if(check(x,y)&&a[x][y]==a[i][j]){
 61                     int nid=(x-1)*m+y;
 62                     int id=(i-1)*m+j;
 63                     int fa1=find(id);
 64                     int fa2=find(nid);
 65                     //bug(fa1);
 66                     fa[fa1]=fa2;
 67                 }
 68             }
 69         }
 70     }
 71     for(int i=1;i<=n*m;i++){
 72         int x=find(i);
 73         cnt[x]++;
 74     }
 75 
 76     int tot[50];
 77     int ma[50];
 78     int b[10][10];
 79 
 80     for(int i=1;i<=n*m;i++)tot[i]=cnt[i],ma[i]=fa[i];
 81 
 82     for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)b[i][j]=a[i][j];
 83     for(int f=1;f<=n*m;f++){
 84         if(cnt[f]>=3){
 85             //bug(f);
 86             for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)flag[i][j]=0;
 87             for(int k=1;k<=n*m;k++){
 88                 if(find(k)!=f)continue;
 89                 int x,y;
 90                 if(k%m==0){
 91                     x=k/m;
 92                     y=m;
 93                 }
 94                 else{
 95                     x=k/m+1;
 96                     y=k%m;
 97                 }
 98                 //printf("%d %d\n",x,y);
 99                 flag[x][y]=1;
100             }
101             for(int i=1;i<=m;i++){
102                 
103                 for(int j=n;j>=1;j--){
104                     int t=0;
105                     for(int k=j+1;k<=n;k++){
106                         if(flag[k][i])t++;
107                     }
108                     a[j+t][i]=a[j][i];
109                 }
110                 int mx=0;
111                 for(int j=1;j<=n;j++)if(flag[j][i])mx++;
112                 for(int k=1;k<=mx;k++){
113                     a[k][i]=0;
114                 }
115             }
116             //printf("%d \n",h);
117             gao(h+1);
118             for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)flag[i][j]=0,a[i][j]=b[i][j];
119             for(int i=1;i<=n*m;i++)cnt[i]=tot[i],fa[i]=ma[i];
120 
121 
122         }
123     }
124 
125 }
126 
127 int main(){
128 
129     IO;
130     cin>>n>>m;
131     for(int i=1;i<=n;i++){
132         for(int j=1;j<=m;j++){
133             cin>>a[i][j];
134         }
135     }
136     
137 
138     gao(0);
139 
140     cout<<ans<<endl;
141 
142     
143     
144     
145 }
146 /*
147 3 5
148 4 4 4 1 4
149 4 2 2 2 1
150 3 3 3 1 4
151 
152 */

 

posted @ 2024-05-27 21:34  Venux  阅读(15)  评论(0编辑  收藏  举报