soj1111 Gnome Tetravex dfs搜索

来源:互联网 发布:fifaonline3国服数据库 编辑:程序博客网 时间:2024/06/05 17:34

这也是黑书上的一道例题。

先给个soj的链接:题目

【题目大意】

给定n*n(N<=5)个方块,每个方块由上下左右四个面构成。

问是否能将n*n个方块拼成任意两个相邻块的相邻面值相等。

实例如下图:

这是一个初始2*2的方块:


它可以拼成如下图形,满足要求:


分析:

这是个典型的搜索问题,属于约束性搜索。

搜索顺序从中间到两边能够比较快的剪掉一些枝。这里用bfs先计算出一个序列,再按照这个序列进行搜索。

由于可能存在完全相同的块,这里存储不同的块和每一块的数量。

通过dfs即可算出。

实事证明还是从头开始搜比较快= =

附个中间搜的代码如下:

#include <string.h>#include <stdio.h>#include <ctype.h>#include <algorithm>#include <queue>using namespace std;const int maxn = 32 ;int num , cnt[maxn] , nn , n , path[maxn] , order[maxn][6] , boundary[maxn][6] , sth ;bool vis[maxn] ;struct node {    int top , right , bottom , left ;}block[maxn];inline bool get(int &t){    bool flag = 0 ;    char c;    while(!isdigit(c = getchar())&&c!='-') if( c == -1 ) break ;    if( c == -1 ) return 0 ;    if(c=='-') flag = 1 , t = 0 ;    else t = c ^ 48;    while(isdigit(c = getchar()))    t = (t << 1) + (t << 3) + (c ^ 48) ;    if(flag) t = -t ;    return 1 ;}void dosth(int k){    queue<int> q;     q.push(k/2*k);    int x , y , i = 0 ;    memset(vis,0,sizeof(vis));    while (!q.empty())    {        boundary[i][k] = 0 ;        x = order[i][k] = q.front();    q.pop();        if(vis[x]) continue;        vis[x] = 1 ;        if( x >= k ) q.push(x-k),boundary[i][k]^=1;        if( x % k != 0 ) q.push(x-1),boundary[i][k]^=2;        if( x % k != k-1 ) q.push(x+1),boundary[i][k]^=4;        if( x / k < k-1 ) q.push(x+k),boundary[i][k]^=8;        i++;    }}void init(){    for( int i = 1 ; i <= 5 ; i++) dosth(i);}bool dfs(int pos){    if( pos == nn ) return true ;    for ( int i = 1 ; i < num ; i++) if( cnt[i] )    {        if( boundary[pos][n] & 1 && path[order[pos][n]-n] && block[path[order[pos][n]-n]].bottom != block[i].top ) continue;        if( boundary[pos][n] & 2 && path[order[pos][n]-1] && block[path[order[pos][n]-1]].right != block[i].left ) continue;        if( boundary[pos][n] & 4 && path[order[pos][n]+1] && block[path[order[pos][n]+1]].left != block[i].right ) continue;        if( boundary[pos][n] & 8 && path[order[pos][n]+n] && block[path[order[pos][n]+n]].top != block[i].bottom ) continue;        path[order[pos][n]] = i ;        cnt[i]--;         if(dfs(pos+1)) return 1 ;        cnt[i]++;         path[order[pos][n]] = 0 ;    }    return false ;}int main(){    int t , k , i , j ;    init();    for ( k = 1 ; get(n) && n ; k++)    {        num = 1 ;        nn = n * n ;        sth = nn - n ;        for( i = 0 ; i < nn ; i++)        {            get(block[num].top);    get(block[num].right); get(block[num].bottom); get(block[num].left);            for( j = 0 ; j < num ; j++)                if( block[num].top == block[j].top &&                     block[num].bottom == block[j].bottom &&                     block[num].right == block[j].right &&                     block[num].left == block[j].left )                    break;            if( j == num ) cnt[num++] = 1 ;            else cnt[j]++;        }        memset(path,0,sizeof(path));        if(dfs(0))    printf("Game %d: Possible\n\n",k);        else printf("Game %d: Impossible\n\n",k);            }}

在附个zoj1008的代码

#include <string.h>#include <stdio.h>#include <ctype.h>#include <algorithm>#include <iostream>#include <queue>using namespace std;const int maxn = 232 ;int num , cnt[maxn] , nn , n , path[maxn] ;bool vis[maxn] ;struct node {    int top , right , bottom , left ;}block[maxn];inline bool get(int &t){    bool flag = 0 ;    char c;    while(!isdigit(c = getchar())&&c!='-') if( c == -1 ) break ;    if( c == -1 ) return 0 ;    if(c=='-') flag = 1 , t = 0 ;    else t = c ^ 48;    while(isdigit(c = getchar()))    t = (t << 1) + (t << 3) + (c ^ 48) ;    if(flag) t = -t ;    return 1 ;}const int cx[] = {1,-1,0,0};const int cy[] = {0,0,1,-1};bool dfs(int pos){    if( pos == nn ) return true ;    int x = pos / n ;    int y = pos % n ;    for ( int i = 0 ; i < num ; i++) if( cnt[i] )    {        if( x && block[path[pos-n]].bottom != block[i].top ) continue;        if( y && block[path[pos-1]].right != block[i].left ) continue;        path[pos] = i ;        cnt[i]--;        if(dfs(pos+1)) return 1 ;        cnt[i]++;    }    return false ;}int main(){    int t , k , i , j ;    for ( k = 1 ; get(n) && n ; k++)    {        num = 0 ;        nn = n * n ;        for( i = 0 ; i < nn ; i++)        {            get(block[num].top);    get(block[num].right); get(block[num].bottom); get(block[num].left);            for( j = 0 ; j < num ; j++)                if( block[num].top == block[j].top &&                     block[num].bottom == block[j].bottom &&                     block[num].right == block[j].right &&                     block[num].left == block[j].left )                    break;            if( j == num ) cnt[num++] = 1 ;            else cnt[j]++;        }bool ff = dfs(0);if(k>1)puts("");cout<<"Game "<<cases++<<": ";if(ff)cout<<"Possible"<<endl;else cout<<"Impossible"<<endl;    }}



原创粉丝点击