zoukankan      html  css  js  c++  java
  • [SCOI2005]骑士精神

    题目:骑士精神

    网址:https://www.luogu.com.cn/problem/P2324

    在一个5×5的棋盘上有12个白色的骑士和12个黑色的骑士,且有一个空位。

    在任何时候一个骑士都能按照骑士的走法(它可以走到和它横坐标相差为1,纵坐标相差为2或者横坐标相差为2,纵坐标相差为1的格子)移动到空位上。

    给定一个初始的棋盘,怎样才能经过移动变成如下目标棋盘:为了体现出骑士精神,他们必须以最少的步数完成任务。

    image

    输入格式

    第一行有一个正整数T(T<=10),表示一共有T组数据。

    接下来有T个5×5的矩阵,0表示白色骑士,1表示黑色骑士,*表示空位。

    两组数据之间没有空行。

    输出格式

    每组数据输出占一行。

    如果能在15步以内(包括15步)到达目标状态,则输出步数,否则输出-1。

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

    本题可以使用IDA*求解。

    很显然,对于一个状态,对空格像8个方向进行枚举即可。

    估价函数怎么运作?

    对于如果当前深度 + 该状态下没有归位的棋子个数 > 所限制的深度,剪枝。

    不对啊,有反例的:最开始只有一个位置与空格互相错位,并且只需1步即可变成目标状态,那么此时的估价大于实际代价,有误!

    因此,估价函数中数量应该是:除空格外,未归位的个数。

    这次没有反例吧!

    代码如下:

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<cmath>
    using namespace std;
    struct rec
    {
    	int x, y;
    } st;
    
    const int dx[8] = {1, 2, 2, 1, -1, -2, -2, -1};
    const int dy[8] = {2, 1, -1, -2, 2, 1, -1, -2};
    const int dc[5][5] = {{1, 1, 1, 1, 1}, {0, 1, 1, 1, 1}, {0, 0, -1, 1, 1}, {0, 0, 0, 0, 1}, {0, 0, 0, 0, 0}};
    int map[5][5];
    
    int calc(int (*mat)[5])
    {
    	int cnt = 0;
    	if(mat[2][2] != -1) cnt = -1;
    	for(int i = 0; i < 5; ++ i)
    	{
    		for(int j = 0; j < 5; ++ j)
    		{
    			if(mat[i][j] != dc[i][j]) ++ cnt;
    		}
    	}
    	return cnt;
    }
    bool valid(int (*mat)[5])
    {
    	for(int i = 0; i < 5; ++ i)
    		for(int j = 0; j < 5; ++ j)
    			if(dc[i][j] != mat[i][j]) return false;	
    	return true;
    }
    bool dfs(int (*book)[5], rec blank, rec fa, int dep)
    {
    	if(calc(book) > dep) return false;
    	if(!dep) return valid(book);
    	int x = blank.x, y = blank.y, mat[5][5];
    	memcpy(mat, book, sizeof(mat));
    	rec q;
    	for(int i = 0; i < 8; ++ i)
    	{
    		q = (rec) {x + dx[i], y + dy[i]};
    		if(q.x < 0 || q.x >= 5 || q.y < 0 || q.y >= 5 || (q.x == fa.x && q.y == fa.y)) continue;
    		
    		swap(mat[x][y], mat[q.x][q.y]);
    		if(dfs(mat, q, blank, dep - 1)) return true;
    		swap(mat[x][y], mat[q.x][q.y]);
    	}
    	return false;
    }
    int main()
    {
    	char c[5][5];
    	int T;
    	scanf("%d", &T);
    	while(T --)
    	{		
    		for(int i = 0; i < 5; ++ i) cin>> c[i];	
    		for(int i = 0; i < 5; ++ i)
    		{
    			for(int j = 0; j < 5; ++ j)
    			{
    				switch(c[i][j])
    				{
    					case '1':
    					{
    						map[i][j] = 1;
    						break;
    					}
    					case '0':
    					{
    						map[i][j] = 0;
    						break;
    					}
    					case '*':
    					{
    						map[i][j] = -1;
    						st.x = i, st.y = j;
    						break;
    					}
    					default: break;
    				}
    			}
    		}
    		bool okay = false;
    		for(int dep = 0; dep <= 15; ++ dep)
    		{
    			if(dfs(map, st, st, dep))
    			{
    				okay = true;
    				printf("%d
    ", dep);
    				break;
    			}
    		}
    		if(!okay) puts("-1");
    	}
    	return 0;
    }
    
  • 相关阅读:
    php编译错误:jpeglib.h not found.
    php编译错误:Please reinstall the libcurl distribution
    php编译错误:Cannot find OpenSSL's <evp.h>
    php shmop windows 信号量锁
    vsftpd配置
    putty ssh 证书登录及问题
    mysql被收购 用mariadb
    centos 7 php7 yum源
    3dmax 欢迎页卡住
    用python进行服务器的监控
  • 原文地址:https://www.cnblogs.com/zach20040914/p/12843869.html
Copyright © 2011-2022 走看看