• 【洛谷 P4289】[HAOI2008]移动玩具(搜索)


    其实这题可以不用状压。。

    提供一种新思路。

    我们在读入目标棋盘的时候,把当前位置的数和当前棋盘进行比较,如果不一样,如果当前是(1),目标是(0),那么我们就把当前位置加入(needmove)队列里去,否则加入(needgot)队列里去。

    然后我们两遍循环,对这两个队列两两匹配,构成一个操作,表示把(needmove)里的一个位置上的(1)移到(needgot)里的一个位置上去,同时保存该操作需要的步数,就是这两个位置的曼哈顿距离。

    然后进行(DFS),枚举所有操作,若这两个位置都没变成目标状态,那么标记一下,进行这个操作,然后回溯。

    还可以加一个最优性剪枝,降低时间复杂度。

    这样,总能得到最优的方案。
    时间复杂度也比较优秀。
    码量也很少。

    #include <cstdio>
    #define Open(s) freopen(s".in","r",stdin);freopen(s".out","w",stdout);
    #define Close fclose(stdin);fclose(stdout);
    int abs(int x){
        return x > 0 ? x : -x;
    }
    struct Node{
        int from, to, dis;
    }e[4000];
    int a[5][5], b[5][5];
    int needmove[20], needgot[20], nm, ng, num, vism[4000], visg[4000], ans = 2147483647;
    inline int read(){
        char ch = getchar();
        while(ch < '0' || ch > '9') ch = getchar();
        return ch - '0';
    }
    void dfs(int sum, int fi, int last){
        if(sum > ans) return;
        if(fi == nm){ ans = sum; return; }
        for(int i = last; i <= num; ++i)
           if(!vism[e[i].from] && !visg[e[i].to]){
             vism[e[i].from] = 1;
             visg[e[i].to] = 1;
             dfs(sum + e[i].dis, fi + 1, i + 1);
             vism[e[i].from] = 0;  //回溯
             visg[e[i].to] = 0;
           }
    }
    int main(){
      //Open("move");
      for(int i = 1; i <= 4; ++i)
         for(int j = 1; j <= 4; ++j)
            a[i][j] = read();
      for(int i = 1; i <= 4; ++i) //得到两个队列
         for(int j = 1; j <= 4; ++j){
            b[i][j] = read();
            if(a[i][j] != b[i][j])
              if(a[i][j] == 1)
                needmove[++nm] = i * 10 + j;
              else
                needgot[++ng] = i * 10 + j;
         }
      for(int i = 1; i <= nm; ++i)  //两两匹配记录所有可能的操作
         for(int j = 1; j <= ng; ++j)
            e[++num].from = needmove[i], e[num].to = needgot[j], 
            e[num].dis = abs(needmove[i] / 10 - needgot[j] / 10) + abs(needmove[i] % 10 - needgot[j] % 10);
      dfs(0, 0, 1);
      printf("%d
    ", ans);
      //Close;
      return 0;
    }
    
    
  • 相关阅读:
    java期末复习2
    java期末复习
    Educational Codeforces Round 76 (Rated for Div. 2)
    ICPC南昌时间安排
    codeforces 597 div2 ABCDF
    codeforces 597 div2 ABC
    Vue中provide和inject 用法
    Js打印九九乘法表
    document.documentElement和document.body的区别
    移动端关于横屏问题
  • 原文地址:https://www.cnblogs.com/Qihoo360/p/9606707.html
Copyright © 2020-2023  润新知