zoukankan      html  css  js  c++  java
  • 《算法竞赛进阶指南》0x28IDA* POJ2286 the rotation game

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

    对于24个数组成的#,一共有8中拉的方式,求使得中间8个数相同的最小操作以及操作方式,由于一个结点扩展的分支有7个,所以朴素dfs将会在无法获得最优解的分支上花费太多时间

    通过枚举操作次数可以避免dfs搜索过深,并且加上未来估计,估计就是8-中间八个数中出现最多的数的出现次数(记做8-s),因为每次移动之后添加进一个新的数,移除的数可能是当前最多的数有可能是其他数

    所以至少还需要8-s次操作,如果当前操作+f()>max_depth,说明搜索不会成功,因为实际操作数一定是大于 当前操作数+估计的最小操作数的

    本题还有个重点就是保存每种操作的下标,便于循环移位,保存中间数的下标便于check是否是终态,保存每种操作的逆操作,便于回溯以及判断是否是还原了上次的操作(需要被舍弃).

    代码:

    /*
            0      1
            2     3
      4  5  6  7  8  9  10
            11    12
      13 14 15 16 17 18 19
              20    21
              22    23
    */
    #include<iostream>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    #define maxn 25
    
    int op[8][7]={//记录每一种操作以及操作的初始值,分别按照操作的次序保存 
        {0,2,6,11,15,20,22},
        {1,3,8,12,17,21,23},
        {10 ,9, 8, 7, 6, 5, 4},
        {19,18,17,16,15,14,13},
        {23,21,17,12,8,3,1},
        {22,20,15,11,6,2,0},
        {13,14,15,16,17,18,19},
        {4,5,6,7,8,9,10}
    };
    //保存相反的操作 
    int opposite[8]={5,4,7,6,1,0,3,2};
    //中间的格子,判断是否一样的时候使用 
    int center[8]={6,7,8,11,12,15,16,17}; 
    
    int q[maxn];
    int path[100];
    int sum[4];
    
    int f(){        
        memset(sum,0,sizeof(sum));
        for(int i=0;i<8;i++)sum[q[center[i]]]++;
        int s=0;
        for(int i=1;i<=3;i++)s=max(s,sum[i]);
        return 8-s;
    }
    
    bool check(){
        for(int i=1;i<8;i++){
            if(q[center[i]]!=q[center[0]])return false;
        }
        return true;
    }
    
    void operate(int x){//循环移位 
        int tmp=q[op[x][0]];
        for(int i=0;i<6;i++){
            q[op[x][i]]=q[op[x][i+1]];
        }
        q[op[x][6]]=tmp;
    }
    
    bool dfs(int depth,int max_depth,int last){//不执行逆操作 
        if(depth+f() > max_depth)return false; 
        if(check())return true;
        
        for(int i=0;i<8;i++){
            if(opposite[i]==last)continue;//当前执行的操作是上一次的逆操作,放弃 
            operate(i);
            path[depth]=i;
            if(dfs(depth+1,max_depth,i))return true;
            operate(opposite[i]);//回溯,也就是执行逆操作 
        }
        
        return false;
    }
    
    int main(){
        while(scanf("%d",&q[0]) && q[0]){
            for(int i=1;i<24;i++)scanf("%d",&q[i]);
            
            int depth=0;
            while(!dfs(0,depth,-1))depth++;
            
            if(!depth)printf("No moves needed");
            else{
                for(int i=0;i<depth;i++)printf("%c",path[i]+'A');            
            }
            printf("
    %d
    ",q[6]);
        }    
        
        return 0;
    } 
  • 相关阅读:
    POJ 1251 Jungle Roads
    1111 Online Map (30 分)
    1122 Hamiltonian Cycle (25 分)
    POJ 2560 Freckles
    1087 All Roads Lead to Rome (30 分)
    1072 Gas Station (30 分)
    1018 Public Bike Management (30 分)
    1030 Travel Plan (30 分)
    22. bootstrap组件#巨幕和旋转图标
    3. Spring配置文件
  • 原文地址:https://www.cnblogs.com/randy-lo/p/13175568.html
Copyright © 2011-2022 走看看