1. 程式人生 > >NKOJ 2440 數字消除遊戲【迭代加深+剪枝】

NKOJ 2440 數字消除遊戲【迭代加深+剪枝】

問題描述

在一個n*n的方形棋盤上玩消除遊戲,棋盤上佈滿了數字。 每一步,玩家可以任選一個數字x,用它填充座標為(1,1)格子所在連通區域,該區域的數字都會變成x。(如果兩個數字相同且相鄰,我們稱這兩個數字連通。相鄰是上下左右四方向)。 當整個棋盤的數字都相同時,就可以將整個棋盤上的數字消除掉,遊戲結束。 問,最少需要幾次操作就能消除所有數字。

輸入格式

有若干組測試資料(不超過20組),對於每組測試資料: 第一行,一個整數n,表示棋盤的尺寸。 接下來一個n*n的數字矩陣,表示遊戲的初始局面。 當輸入的n==0時,輸入結束。

輸出格式

對於每組測試資料,輸出一行,一個整數,表示最少需要的運算元。

在這裡插入圖片描述

#include <map>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define ll long long
#define rep(i,x,y) for(ll i=(x);i<=(y);i++)
#define repl(i,x,y) for(ll i=(x);i<(y);i++)
#define repd(i,x,y) for(ll i=(x);i>=(y);i--)
using namespace std;

const ll N=10;

ll n,tim,mp[N][N],vis[N][N];

ll dx[4]={0,0,-1,1};
ll dy[4]={-1,1,0,0};

map<ll,ll>Hash;

inline ll read() {
	ll x=0;char ch=getchar();bool f=0;
	while(ch>'9'||ch<'0'){if(ch=='-')f=1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
	return f?-x:x;
}

void dfs(ll x,ll y,ll z) {
	vis[x][y]=1;
	
	rep(i,0,3) {
		ll tx=x+dx[i],ty=y+dy[i];
		
		if(tx<1||ty<1||tx>n||ty>n||vis[tx][ty]==1) continue;
		
		vis[tx][ty]=2;
		
		if(mp[tx][ty]==z) dfs(tx,ty,z);
	}
}

ll getleft() {
	ll ret=0,col[7]={0};
	rep(i,1,n) rep(j,1,n) if(!col[mp[i][j]]&&vis[i][j]!=1) {
		col[mp[i][j]]=1;ret++;
	}return ret;
}

ll getfill(ll z) {
	ll ret=0;
	rep(i,1,n) rep(j,1,n) if(mp[i][j]==z&&vis[i][j]==2) {
		++ret;dfs(i,j,z);
	}return ret;
}

ll idastar(ll dep,ll lim) {
	ll ret=getleft();
	
	if(dep+ret>lim) return 0;
	
	if(!ret) return 1;
	
	ll vvis[N][N]={0};
	
	rep(i,1,tim) {
		memcpy(vvis,vis,sizeof(vis));
		if(getfill(i)&&idastar(dep+1,lim)) return 1;
		memcpy(vis,vvis,sizeof(vis));
	}
	
	return 0;
}

int main() {
	while(true) {
		n=read();
		
		if(!n) return 0;
		
		while(Hash.size()) Hash.erase(Hash.begin());
		
		tim=0;
		
		rep(i,1,n) rep(j,1,n) {
			mp[i][j]=read();
			if(!Hash[mp[i][j]]) Hash[mp[i][j]]++;mp[i][j]=Hash[mp[i][j]];
		}
		
		memset(vis,0,sizeof(vis));
		
		dfs(1,1,mp[1][1]);
		
		rep(dep,0,N*N) if(idastar(0,dep)) {
			printf("%lld\n",dep);break;
		}
	}

	return 0;
}