消除之王

来源:互联网 发布:软件项目实施工作总结 编辑:程序博客网 时间:2024/06/11 03:15

消除之王

Time Limit : 3000/1000ms (Java/Other)   Memory Limit : 65535/32768K (Java/Other)
Total Submission(s) : 7   Accepted Submission(s) : 3

Font: Times New Roman | Verdana | Georgia

Font Size: ← →

Problem Description

自从shoushou同学下了 popstar(http://www.pc6.com/azyx/78703.html)这个游戏之后便疯狂的玩了起来。 但是因为shoushou的IQ比较低,每次都拿不到高分,shoushou很生气,你能帮帮他吗?
为了将问题简化,题目将给出大小为n*m (1<=n<=4,1<=m<=4)的只含0,1的矩阵。你每次可以选择一个区域(连续不间断),如果这个区域所含的格子数大于1,而且全部为0或者全部为1的时候就可以将这块区域消除。(注意:而且与这个区域相连通的同颜色的格子也同样会消除! )之后如果剩下来的任意一个格子的下方为空的时候,就会向下移动直到到达最底端或下方出现其他格子。 也就是说每个格子都会下落! 需要注意的是:格子只会向下移动而不会左右移动!
举个例子:

给出了一个4*4的矩阵

0011
0000
0011
0000

- . - - . - - . -- . -- . -- . -- . -- . -- . -- . -- . -- . -- . -- . --- . --- . --- . --- . --- . -

当我们选择
00
0000
00
0000
这个区域消除的话,就会变成
....
....
..11
..11 ('.'代表空)
- . - - . - - . -- . -- . -- . -- . -- . -- . -- . -- . -- . -- . -- . --- . --- . --- . --- . --- . -
现在问题来了,你可以进行任意多次的这种消除操作,求所留下来的最小格子数是多少?
显然前面给出的例子可以全部消除完,也就是还剩下0个格子。

Input

输入的第一行是T,代表的测试数据组数
每组数据的开始是n,m(1<=n<=4,1<=m<=4).代表了行数和列数
然后是n行,每行包括m个字符 (只为1或0)。

Output

输出一行表示最小的格子数

Sample Input

21 114 41010010110100101

Sample Output

116
 //code:
#include <iostream>#include <cstdio>#include <cstring>#include <queue>using namespace std;struct State{int map[4][4];void InitState()//对棋盘的初始化。{for(int i=0;i<4;i++)for(int j=0;j<4;j++)map[i][j] = -1;}void InitS()//对连通性表示的初始化。{memset(map,0,sizeof(map));}State operator = ( const State var){State tmp;for(int i=0;i<4;i++)for(int j=0;j<4;j++)tmp.map[i][j] = var.map[i][j];return tmp;}int Count()//计算连通块所含棋子数。{int num = 0;for(int i=0;i<4;i++)for(int j=0;j<4;j++)if(map[i][j]) num++;return num;}State Adujust(State p)//消除连通块后下调{State tmp;tmp.InitState();for(int i=3;i>=0;i--)for(int j=0;j<4;j++){if(!p.map[i][j] && map[i][j] != -1){int k = i;while(k<=3 && tmp.map[k][j] == -1)k++;if(tmp.map [k][j]!=-1) k--;tmp.map [k][j] = map[i][j];}}return tmp;}int ReCount()//统计不能消除的块数。{int num = 0;for(int i=0;i<4;i++)for(int j=0;j<4;j++)if(map[i][j] != -1) num++;return num;}void operator +=(const State p){for(int i=0;i<4;i++)for(int j=0;j<4;j++)map[i][j] |= p.map[i][j];}};void dfs(int x,int y,State var,int obj,State &p)//深搜连通块{if(x<0 || y<0 || x>=4 || y>=4) return ;if( var.map[x][y] != obj || p.map [x][y]) return ;p.map[x][y] = 1;dfs(x+1,y,var,obj,p);dfs(x,y+1,var,obj,p);dfs(x,y-1,var,obj,p);dfs(x-1,y,var,obj,p);}int bfs(State var,State &p,int x,int y){p.InitS();if(var.map[x][y] == -1)  return 0;dfs(x,y,var,var.map[x][y],p);return p.Count();}int MinStep(State var)//求最小剩余{int flag=0;int Min = 256;State is;is.InitS();for(int i=0;i<4;i++)for(int j=0;j<4;j++){if(var.map[i][j] != -1 && !is.map[i][j]){State p;int t = bfs(var,p,i,j);if(t>1 ){is += p;State tk = var.Adujust(p);flag = 1;t = MinStep(tk);if(t<Min) Min = t;}}}if(!flag) return var.ReCount();else return Min;}int main(){int t;scanf("%d",&t);while(t--){int n,m;scanf("%d%d",&n,&m);State s;s.InitState();for(int i=0;i<n;i++){char st[10];scanf("%s",st);for(int j=0;j<m;j++) s.map[i][j] = st[j]-'0';}printf("%d\n",MinStep(s));}return 0;}
原创粉丝点击