NKOI 2440 数字消除游戏

原创 2016年08月29日 18:08:39

数字消除游戏

问题描述
    在一个n*n的方形棋盘上玩消除游戏,棋盘上布满了数字。
    每一步,玩家可以任选一个数字x,用它填充坐标为(1,1)格子所在连通区域,该区域的数字都会变成x。(如果两个数字相同且相邻,我们称这两个数字连通。相邻是上下左右四方向)。
    当整个棋盘的数字都相同时,就可以将整个棋盘上的数字消除掉,游戏结束。
    问,最少需要几次操作就能消除所有数字。

输入格式

有若干组测试数据(不超过20组),对于每组测试数据:
第一行,一个整数n,表示棋盘的尺寸。
接下来一个n*n的数字矩阵,表示游戏的初始局面。

当输入的n==0时,输入结束。

输出格式

对于每组测试数据,输出一行,一个整数,表示最少需要的操作数。

样例输入

2
1 3 
3 3
4
5 5 2 0
5 5 2 0
2 2 2 0
0 0 0 2
0

样例输出
1
3

提示

样例说明,对于第二组数据:
第1步 选数字2去填充,得到:
2 2 2 0
2 2 2 0
2 2 2 0
0 0 0 2
第2步 选数字0去填充,得到:
0 0 0 0
0 0 0 0
0 0 0 0
0 0 0 2
第3步 选数字2去填充,得到:
2 2 2 2
2 2 2 2
2 2 2 2
2 2 2 2
对于100%的数据,n<=8,
初始棋盘中最多有6种不同的数字

思路:枚举每次选取了哪种数字,然后找出左上角的格子所在的联通块,改变数字。

由于步数的不确定,应该使用迭代加深搜索
加入一个小剪枝:如果改变数字后,左上角格子所在的联通块大小没有改变,可以剪枝。这样可以避免来回往复地搜索。
采用IDA*算法,设计估价函数。可以发现如果当前矩阵中除了左上角的联通块之外,共有M种数字,那么还需要的步数不小于M。因此如果当前搜索深度+估价函数的值>深度限制,可以回溯。

我们可以发现,每次寻找左上角的格子所在的联通块耗费的时间常数巨大。因此我们在这里寻求突破。
我们引入一个N*N的v数组。左上角的格子所在的联通块里的格子标记为1。左上角联通块周围一圈格子标记为2,其它格子标记为0。如果某次选择了数字c,我们只需要找出标记为2并且数字为c的格子,向四周扩展,并相应地修改v标记,就可以不断扩大标记为1的区域,最终如果所有格子标记都是1,那么显然找到了答案。

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdlib>
using namespace std;
const int inf=1e9;
inline void _read(int &x){
    char t=getchar();bool sign=true;
    while(t<'0'||t>'9')
    {if(t=='-')sign=false;t=getchar();}
    for(x=0;t>='0'&&t<='9';t=getchar())x=x*10+t-'0';
    if(!sign)x=-x;
}
int dx[4]={-1,1,0,0};
int dy[4]={0,0,-1,1};
int n,vis[6],s[10][10],v[10][10],depth;
int geth(){
	int i,j,temp=0;
	memset(vis,0,sizeof(vis));
	for(i=1;i<=n;i++)
	    for(j=1;j<=n;j++)
	        if(!vis[s[i][j]]&&v[i][j]!=1){
			    vis[s[i][j]]=1;
			    temp++;
			}
	return temp;
}
void paint(int x,int y,int c){
	v[x][y]=1;
	for(int i=0;i<4;i++){
		int tx=x+dx[i],ty=y+dy[i];
		if(tx<1||tx>n||ty<1||ty>n||v[tx][ty]==1)continue;
		v[tx][ty]=2;
		if(s[tx][ty]==c)paint(tx,ty,c);
	}
}
int check(int c){
	int i,temp=0,j;
	for(i=1;i<=n;i++)
	    for(j=1;j<=n;j++)
	        if(v[i][j]==2&&s[i][j]==c){
	        	temp++;
	        	paint(i,j,c);
	        }
	return temp;
}
bool dfs(int k){
	int h=geth();
	if(k+h>depth)return 0;
	if(h==0)return 1;
	int res[10][10],i;
	for(i=0;i<=5;i++){
		memcpy(res,v,sizeof(v));
		if(check(i)&&dfs(k+1))return 1;
		memcpy(v,res,sizeof(res));
	}
	return 0;
}
int main(){
	while(cin>>n&&n){
		for(int i=1;i<=n;i++)
		    for(int j=1;j<=n;j++)
		        scanf("%d",&s[i][j]);
		memset(v,0,sizeof(v));
		paint(1,1,s[1][1]);
		for(depth=0;;depth++)
		    if(dfs(0))break;
		printf("%d\n",depth);
	}
}


版权声明:本文为博主原创文章,未经博主允许不得转载。

CCF之消除类游戏(java)

试题编号: 201512-2 试题名称: 消除类游戏 时间限制: 1.0s 内存限制: 256.0MB 问题描述: ...
  • zjj582984208
  • zjj582984208
  • 2017年02月15日 21:06
  • 1068

消除类游戏核心算法

如今三消类游戏很多,比如:消灭寿司,消灭星星
  • u014096244
  • u014096244
  • 2014年10月28日 15:55
  • 1807

数字消除游戏

.h #ifndef __GAMETWO_SCENE_H__ #define __GAMETWO_SCENE_H__ #include "cocos2d.h" #include...
  • hj3601947
  • hj3601947
  • 2014年07月24日 20:43
  • 457

分享一个完整程序的代码(消除类游戏)

AppDelegate.cpp#include "AppDelegate.h" #include"WelcomeScene.h" #include "SimpleAudioEngine.h"//声...
  • HLW0522
  • HLW0522
  • 2016年07月08日 16:24
  • 3047

消除游戏下落算法(竖直和斜向)

1. @Override public void act(float delta) { super.act(delta); if (isCouldTouch()) { guid...
  • themagickeyjianan
  • themagickeyjianan
  • 2016年09月29日 19:16
  • 1073

消除游戏之消除算法

int test::Check(int x, int y) { m_delete[x][y] = true;//表示相邻对象是一类 int nLeft = 0; if (x > 0) { ...
  • ganpengjin1
  • ganpengjin1
  • 2015年06月19日 10:30
  • 1497

告诉大家。cocos2d 简单消除游戏算法 (一)

1. 游戏视频演示 2.三消游戏我的理解 上面视频中的游戏,我做了2个星期时间,只能算个简单Demo,还有bug,特效也几乎没有。感觉三消游戏主要靠磨,越磨越精品。...
  • w5223336
  • w5223336
  • 2014年10月20日 23:17
  • 5970

消除类游戏案例:Sushi Crush(二)

在上一节《使用Cocos2d-x制作三消类游戏Sushi Crush——第一部分》中,我们完成了分辨率的适配和寿司精灵的创建、布局、下落。按照三消游戏的游戏制作流程,接下来我们实现寿司精灵的消除操作。...
  • huangbaiyi
  • huangbaiyi
  • 2015年04月28日 19:20
  • 469

NOI 2014简要题解

Day 1.Problem A. 起床困难综合症100分做法:把数字看成二进制数。对于初始攻击力,我们将其拆成32位,并求出每一位为0和1时经过所有防御门之后分别得到的数字。然后就是按位贪心了,我们尽...
  • qpswwww
  • qpswwww
  • 2015年07月09日 17:15
  • 1389

【NOI 2014】总结

这两天做了一下NOI2014的题目,虽然分数并不理想,但b
  • Yves___
  • Yves___
  • 2014年08月10日 22:13
  • 950
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:NKOI 2440 数字消除游戏
举报原因:
原因补充:

(最多只允许输入30个字)