• POJ 2286


    题意

    一个 ” # ” 字形图形, 每个横/竖条有七个小方块, 只用1/2/3标记. 其中有八个(ABCDEFG)移动方向, 要通过一些移动操作使得中间的八个小方块的标记相同. 求解这个操作方式以及中间八个小方块相同的标记
    POJ-2286

    思路

    迭代深搜
    剪枝 : 当前需要被改变的小块数量 + 当前操作深度 > 迭代的最大操作深度
    则一定无法达成, 剪枝

    if( remain() + d > maxd ) return false; //剪枝

    AC代码

    #include <iostream>
    #include <algorithm>
    #include <cstring>
    #include <string>
    #include <vector>
    #include <cstdio>
    #include <cmath>
    
    #define mst(a) memset(a, 0, sizeof(a))
    
    using namespace std;
    int n, m;
    const int maxn = 10;
    int mrk[10][10] = {  //标号
        {0,2,6,11,15,20,22},    //A
        {1,3,8,12,17,21,23},    //B
        {10,9,8,7,6,5,4},       //C
        {19,18,17,16,15,14,13}, //D
        {23,21,17,12,8,3,1},    //E
        {22,20,15,11,6,2,0},    //F
        {13,14,15,16,17,18,19}, //G
        {4,5,6,7,8,9,10}        //H
    };
    int mid[] = {6,7,8,11,12,15,16,17}; //中间的八块
    int r[] = {5,4,7,6,1,0,3,2};  //反向
    int g[30];
    char op[1000+10]; //记录操作
    int maxd;
    
    bool judge(){  //判断中间八个是否相同
        for( int i = 1; i < 8; i++ )
            if( g[mid[i]] != g[mid[i-1]] )
                return false;
        return true;
    }
    
    int remain(){
        int re = 10;
        for( int i = 1; i <= 3; i++ ){
            int cnt = 0;
            for( int j = 0; j < 8; j++ )
                if( g[mid[j]] != i )
                    cnt++;
            re = min(re, cnt);
        }
        return re;
    }
    
    void mmove( int x ){  //移动
        int temp = g[mrk[x][0]];
        for( int i = 0; i < 6; i++ )
            g[mrk[x][i]] = g[mrk[x][i+1]];
        g[mrk[x][6]] = temp;
        return;
    }
    
    bool dfs( int d ){
        if( d == maxd ){
            if( judge() ){
                op[d] = '';
                return true;
            }
            else return false;
        }
        if( remain() + d > maxd ) return false; //剪枝
        for( int i = 0; i < 8; i++ ){
            char c = 'A' + i;
            op[d] = c;
            mmove(i);
            if( dfs(d+1) )  return true;
            mmove(r[i]);  //还原移动
            /*  看到dalao们是这么写还原移动的~ 记录一下
                if(i%2==0)  mmove((i+5)%8);
                else  mmove((i+3)%8);
            */
        }
        return false;
    }
    
    void solve(){
        for( maxd = 1; ; maxd++ )
            if( dfs(0) )
                break;
        printf("%s
    ",op);
    }
    
    int main()
    {
        while( scanf("%d",&g[0]) == 1 && g[0] ){
            for( int i = 1; i <= 23; i++ )
                scanf("%d",&g[i]);
            if( judge() )  puts("No moves needed");
            else solve();
            printf("%d
    ",g[mid[0]]);
        }
        return 0;
    }
    
    /*
            A     B
            0     1
            2     3
    H 4  5  6  7  8  9  10 C
            11    12
    G 13 14 15 16 17 18 19 D
            20    21
            22    23
            F     E
    
    */
    
  • 相关阅读:
    hibernate连接MySQL配置hibernate.cfg.xml
    行百里者半九十 —— 查找算法
    行百里者半九十 —— 链表(1)
    行百里者半九十 —— 查找算法(中等)
    行百里者半九十 —— 字符串
    设计模式 —— 总结
    并发编程 —— 使用条件变量构建线程安全队列
    行百里者半九十 ——栈与队列
    设计模式 —— 命令模式
    css选择器中:firstchild与:firstoftype的区别
  • 原文地址:https://www.cnblogs.com/JinxiSui/p/9740579.html
Copyright © 2020-2023  润新知