• POJ1753 Flip Game


    对我来说,此题不易。此题是BFS+状态位压缩。参考:http://blog.csdn.net/hackbuteer1/article/details/7392245
    1. BFS也可以用来求最优解。
    2. 要理解棋盘上任何一个子,所有翻奇数次和所有翻偶数次都是等效的。可以想象假设其他子不翻(这是其他棋子翻过得某个状态),只翻某一个子。那么它翻0次和翻2次结果是一样的。由于求最小值,所以任何一个子只能翻0次或1次。
    3. 所以最多有2^16个状态。
    4. 状态可以压缩。比如
    bwwb
    bbwb
    bwwb
    bwww
    可以表示成1001 1101 1001 1000,也就是十进制40344。
    5. 对每一个要反转的子,(1 << (3 - i) * 4 + (3 - j)),它和它周围的四个子都要翻转,这种翻转可以用二进制表示,之后去和每个状态异或。先把这些状态计算出来。计算如下:

    int[] dx = new int[] {1, -1, 0, 0};
    int[] dy = new int[] {0, 0, 1, -1};
    for (int i = 0; i < 4; i++)
    {
        for (int j = 0; j < 4; j++)
        {
            int state = 0;
            state ^= 1 << (3 - i) * 4 + (3 - j);
            for (int k = 0; k < 4; k++)
            {
                int x = i + dx[k];
                int y = j + dy[k];
                if (x < 0 || y < 0 || x > 3 || y > 3) continue;
                state ^= 1 << (3 - x) * 4 + (3 - y);
            }
            System.out.println(state);
        }
    }
    

    本想用Java做的,结果内存超出,只好用C++了。visit[state] = true;要放在节点push到queue之前,否则之后queue中的元素会在flood的时候flood到这些节点,重复计算。

    #include <iostream>
    #include <queue>
    #include <cstdio>
    #include <memory.h>
    using namespace std;
    
    struct Node
    {
        int state;
        int step;
    };
    
    bool visit[65536]; // 2^16
    int change[16] =
    {
            51200, 58368, 29184, 12544,
            35968, 20032, 10016, 4880,
            2248, 1252, 626, 305,
            140, 78, 39, 19
    };
        
    int bfs(int state)
    {
        memset(visit, false, sizeof(visit));
        queue<Node> queue;
        Node cur, next;
        cur.state = state;
        cur.step = 0;
        queue.push(cur);
        visit[state] = true;
        while (!queue.empty())
        {
            cur = queue.front();
            queue.pop();
            if (cur.state == 0 || cur.state == 0xffff) return cur.step;
            
            for (int i = 0; i < 16; i++)
            {
                next.state = cur.state ^ change[i];
                next.step = cur.step + 1;
                if (visit[next.state]) continue;
                visit[next.state] = true;
                queue.push(next);
            }
        }
        return -1;
    }
    
    int main(void)
    {
        char ch[5][5];
        while(scanf("%s",ch[0])!=EOF)
        {
            for(int i = 1 ; i < 4 ; i++)
                scanf("%s",ch[i]);
            int state = 0;
            for(int i = 0 ; i < 4 ; i++)
            {
                for(int j = 0 ; j < 4 ; j++)
                {
                    state <<= 1;
                    if(ch[i][j] == 'b')
                        state += 1;
                }
            }
            int ans = bfs(state);
            if(ans == -1)
                puts("Impossible");
            else
                printf("%d
    ",ans);
        }
        return 0;
    }
    

      

  • 相关阅读:
    RepositoryItemComboBox 用法1
    php 直接获取url参数赋值成变量。省去繁琐的获取参数,再一个个赋值
    什么是经验,就是解决问题的能力!!
    win7 上运行 php7 +
    win2008 server 多IP配置
    mysqlli 的基本用法
    PHP操作mongoDB 笔记
    关于PHP程序员技术职业生涯规划 转自 韩天锋
    linux 简单笔记
    ubantu 重启mysql
  • 原文地址:https://www.cnblogs.com/lautsie/p/3360018.html
Copyright © 2020-2023  润新知