zoukankan      html  css  js  c++  java
  • 洛谷P2324 bzoj1085 [SCOI2005]骑士精神

    P2324 [SCOI2005]骑士精神

    题目描述

    输入输出格式

    输入格式:

    第一行有一个正整数T(T<=10),表示一共有N组数据。接下来有T个5×5的矩阵,0表示白色骑士,1表示黑色骑士,*表示空位。两组数据之间没有空行。

     

    输出格式:

    对于每组数据都输出一行。如果能在15步以内(包括15步)到达目标状态,则输出步数,否则输出-1。

     

    输入输出样例

    输入样例#1: 复制
    2
    10110
    01*11
    10111
    01001
    00000
    01011
    110*1
    01110
    01010
    00100
    
    输出样例#1: 复制
    7
    -1
    

    说明

    这道题是一道很好的搜索题 结合了迭代加深搜索还有$A*$

    考虑到枚举棋子走法很麻烦 并且只有一个空格 所以考虑到走空格 每次有$8$种走法 开个增量数组搞一搞就可以了

    迭代加深首先肯定是枚举走的最多的次数 然而这个玩意还是要T

    所以使用$A*$估价函数 怎么估呢

    考虑到每次移动空格至多使一个棋子走到目标位置 所以统计有多少棋子不在正确的位置上 这就是最少步数

    如果最少步数加上当前步数超界就返回

    代码

    #include <bits/stdc++.h>
    #define oo 1e9
    using namespace std;
    
    int n, tag, T, x, y, s[10][10], G[10][10];
    int zl[8][2] = {{-2,-1},{-1,-2},{1,-2},{2,-1},{2,1},{1,2},{-1,2},{-2,1}};
    char h[10];
    int g[10][10] = {{0,0,0,0,0,0},
                     {0,1,1,1,1,1},
                     {0,0,1,1,1,1},
                     {0,0,0,2,1,1},
                     {0,0,0,0,0,1},
                     {0,0,0,0,0,0}
    };
    
    void init( ) {
        
        for(int i = 1;i <= 5;i ++) {
            for(int j = 1;j <= 5;j ++) s[i][j] = G[i][j];
        }
    }
    
    bool check( ) {
        
        for(int i = 1;i <= 5;i ++)
            for(int j = 1;j <= 5;j ++) {
                if(i == j) {
                    if(i <= 2) if(s[i][j] != 1) return false;
                    if(i == 3) if(s[i][j] != 2) return false;
                    if(i >= 4) if(s[i][j] != 0) return false;
                }
                if(i < j && s[i][j] != 1) return false;
                if(i > j && s[i][j] != 0) return false;
            }
        return true;
    }
    
    int eval( ) {
        
        int cnt = 0;
        for(int i = 1;i <= 5;i ++)
            for(int j = 1;j <= 5;j ++) {
                if(s[i][j] != g[i][j] && s[i][j] != 2) cnt ++;
            }
        return cnt;
    }
    
    void dfs(int step, int lim, int x, int y) {
        
        if(step == lim) {
            if(check( )) tag = min(tag, step);
            return ;
        }
        int res = eval( );
        if(step + res > lim) return ;
        if(check( )) {tag = min(tag, step); return ;}
        for(int i = 0;i < 8;i ++) {
            int xx = x + zl[i][0], yy = y + zl[i][1];
            if(xx > 5 || xx < 1 || yy < 1 || yy > 5) continue;
            swap(s[x][y], s[xx][yy]);
            dfs(step + 1, lim, xx, yy);
            swap(s[x][y], s[xx][yy]);
        }
    }
    
    void Solve( ) {
        
        scanf("%d",& T);
        while(T --) {
            for(int i = 1;i <= 5;i ++) {
                scanf("%s",h + 1);
                for(int j = 1;j <= 5;j ++) {
                    if(h[j] == '0') G[i][j] = 0;
                    else if(h[j] == '1') G[i][j] = 1;
                    else {
                        G[i][j] = 2; x = i, y = j;
                    }
                }
            }
            tag = oo; init( );
            for(int i = 0;i <= 15;i ++) {
                //init( );
                dfs(0, i, x, y);
                if(tag != oo) {
                    printf("%d
    ", i); break;
                }
            }
            if(tag == oo) printf("-1
    ");
        }
    }
    
    int main( ) {
        
        Solve( );
    }
  • 相关阅读:
    android ListView美化-->几个比较特别的属性
    微博开发第一讲 知识点--2014.04.23
    ubuntu snap install 代理设置
    君正X2000开发板试用体验之二:君正X2000引导过程分析
    君正X2000开发板试用体验之一:开箱
    消除USB麦克风的电流声
    IT专业词汇中文译名探讨
    PCI/PCIE总线的历史
    龙芯派ejtag.cfg设置
    uos运行ejtag报错,找不到libreadline.so.6, libncurses.so.5, libusb-0.1.so.4
  • 原文地址:https://www.cnblogs.com/Rubenisveryhandsome/p/9768986.html
Copyright © 2011-2022 走看看