poj 1753

来源:互联网 发布:淘宝网肚皮舞服装新款 编辑:程序博客网 时间:2024/06/08 18:00

题目概述

给定一4*4棋盘,每个位置有棋子,棋子黑面或白面朝上,每次可选一棋子翻转,其上下左右一格的棋子同时翻转,问可否使所有棋子同色朝上,若可,求最少需选几个棋子

时限

1000ms/3000ms

输入

共4行,每行4个字符,b代表黑面朝上,w代表白面朝上

限制

没有限制

输出

若可以,输出一数,最少选定棋子数,否则输出字符串Impossible

样例输入

case 1:

bwwb
bbwb
bwwb
bwww

case 2:

wwww
wwww
wwww
wwww

case 3:

wwww
wwww
wwww
wwwb

case 4:

wbww
bbbw
wbww
wwww

样例输出

case 1:

4

case 2:

0

case 3:

Impossible

case 4:

1

讨论

广搜,而且需要二进制及其操作,赋予电脑整体思考的能力,将棋盘上每个位置视为一个二进制位,如此一共16位,一个short正好,不过为求方便,实际使用的是unsigned short,因为不会牵扯符号问题且两个边界值很好表示,0和USHRT_MAX,采用广搜以求最少次数,每次搜索将上一次的值记录下,便于最后链式统计次数
如果棋盘再大一些咋办?那就得用bitset了把,比直接用二进制差不少呢

题解状态

292K,0MS,C++,1093B

题解代码

#include<cstdio>#include<cstring>#include<algorithm>#include<cmath>#include<queue>using namespace std;#define INF 0x3f3f3f3f  #define MAXN 16#define memset0(a) memset(a,0,sizeof(a))#define EPS 1e-6unsigned short B, marked[65536], opt[16] = { 0xc800,0xe400,0x7200,0x3100,0x8c80,0x4e40,0x2720,0x1310,0x08c8,0x04e4,0x0272,0x0131,0x008c,0x004e,0x0027,0x0013 };//Bytes 以双字节存放棋盘原始数据 marked 存放广搜时上一次的B值 operator 棋盘上可行的16种翻转操作 以十六进制表示 用win7的计算器可以很方便算出queue<unsigned short>q;//广搜辅助队列int bfs(unsigned short B)//广搜 返回值是次数 不可能返回-1{    q.push(B);    while (!q.empty()) {        B = q.front();        q.pop();        if (!B || B == USHRT_MAX) {//分别代表全白和全黑            int times = 0;            while (marked[B] != USHRT_MAX) {//直到遇到起点标志为止                times++;                B = marked[B];//链式倒推会起点 也可以顺便把每一步记录下来            }            return times;        }        for (int p = 0; p < 16; p++)            if (!marked[B^opt[p]]) {//由于是广搜 因而先到者必然比后到者次数少 因而忽略后到者 异或操作表示翻转                marked[B^opt[p]] = B;//记录来源状态                q.push(B^opt[p]);            }    }    return -1;//所有状态都已搜索过 无法完成}int main(void){    //freopen("vs_cin.txt", "r", stdin);    //freopen("vs_cout.txt", "w", stdout);    for (int p = 15; p >= 0; p--) {        char c;        scanf("%c", &c);//input        if (p % 4 == 0)            getchar();//吞掉换行        if (c == 'b')            B |= 1 << p;//以或和左移操作置位 棋盘左上角为高位    }    marked[B] = USHRT_MAX;//代表全黑的情况 但由于不会有哪个状态由终点衍生 因而作为起点标志    int ans = bfs(B);    if (ans == -1)        printf("Impossible\n");//output    else        printf("%d\n", ans);//output}

EOF

0 0
原创粉丝点击