POJ 1753 Flip Game(暴力+DFS)

来源:互联网 发布:linux 效率 编辑:程序博客网 时间:2024/05/17 03:01

题目链接:http://poj.org/problem?id=1753

题        意:找出是所给的4*4由b,w组成的矩阵全部变为一种字符所需的步数。

思        路:其实每格棋子最多只可以翻转一次(实际是奇数次,但这没意义),

                    只要其中一格重复翻了2次(不论是连续翻动还是不连翻动),那么它

                   以及周边的棋子和没翻动时的状态是一致的,由此就可以确定这个

                   棋盘最多只能走16步,最多只能有翻出2^16种状态。所以直接递归

                   遍历17种情况(还有0步)即可。

代码如下:

#include <iostream>using namespace std;#include <string.h>#include <stdio.h>#include <queue>#include <algorithm>typedef long long LL;int vis[6][6],ans,step;int dx[5]= {0,1,-1,0,0};int dy[5]= {0,0,0,-1,1};int judge(){    for( int i = 1; i < 5; i ++ )        for( int j = 1; j < 5; j ++ )            if(vis[i][j] != vis[1][1] )                return 0;    return 1;}void fz(int x, int y ){    for( int i = 0; i < 5; i ++ )        vis[x+dx[i]][y+dy[i]]=!vis[x+dx[i]][y+dy[i]];    return ;}void dfs(int x, int y, int deep ){    if( deep == step )    {        ans = judge();        return;    }    if( ans ) return;    if(  y >= 5 ) return;//列数已经递归结束    fz(x,y);    if( x < 4 ) //看这一列是否到底,若不到,则继续;若到则从下一列的第一个位置开始        dfs(x+1, y, deep+1 );    else dfs( 1, y+1, deep+1 );    fz(x,y);//上面的操作无法使条件成立则会到这一步,把原来所翻转的棋子还原;再继续下一步    if( x < 4 ) dfs(x+1, y, deep );    else dfs( 1, y+1, deep );    return;}int main(){    memset(vis, 0, sizeof(vis) );    for( int i = 1; i < 5; i ++ )        for( int j = 1; j < 5; j ++ )        {            char ch;            scanf ( " %c", &ch );            if( ch == 'b' ) vis[i][j] = 1;        }    ans = 0;//操作步数从0到16的情况    for( step = 0; step < 17; step ++ )    {        dfs(1,1,0);        if(ans) break;    }    if(ans) printf("%d\n",step);    else printf("Impossible\n");    return 0;}

0 0