1. 程式人生 > >P2324 [SCOI2005]騎士精神

P2324 [SCOI2005]騎士精神

flag while span style dfs img tps 空格 -o

題目描述

技術分享圖片

輸入輸出格式

輸入格式:

第一行有一個正整數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

說明

技術分享圖片

很顯然,我們搜索時應註意搜索空格,而不是馬……

顯然,如果讀入map[i][j]!=所需要的,顯然ans++,所以我們可以求出ans的下界,即mnnd(min_need)。

註意有些優化在裏面,看代碼就知道了。

AC代碼如下:

#include<cstdio>
#include<algorithm>
#include<iostream>
using namespace std;
const int check[6][6]={{},{0,1,1,1,1,1},{0,0,1,1,1,1},{0,0,0,-1,1,1},{0,0,0,0,0,1},{0,0,0,0,0,0}};
const int dx[]={-2,-2,-1,1,-1,1,2,2};
const int dy[]={-1,1,2,2,-2,-2,-1,1};
int mxnd,mnnd,a[1<<3
][1<<3],x,y,t; char b; bool dfs(int step,int x,int y,int nd,int last) { if(step+nd>mxnd) return 0; if(nd==0) return 1; int xx,yy,now; for(int i=0;i<=7;i++) if(i!=7-last) { xx=x+dx[i];yy=y+dy[i]; now=nd; if(xx<=5&&xx>=1&&yy<=5&&yy>=1
) { if(a[xx][yy]==check[xx][yy]&&a[xx][yy]!=check[x][y]) now++; if(a[xx][yy]!=check[xx][yy]&&a[xx][yy]==check[x][y]) now--; if(check[xx][yy]==-1) now--; if(check[x][y]==-1) now++; a[xx][yy]^=a[x][y];a[x][y]^=a[xx][yy];a[xx][yy]^=a[x][y]; if(dfs(step+1,xx,yy,now,i)) return 1; a[xx][yy]^=a[x][y];a[x][y]^=a[xx][yy];a[xx][yy]^=a[x][y]; } } return 0; } int main() { scanf("%d",&t); while(t--) { mnnd=0; for(int i=1;i<=5;i++) for(int j=1;j<=5;j++) { cin>>b; a[i][j]=b-0; if(b==*) x=i,y=j,a[i][j]=-1; if(a[i][j]!=check[i][j]) mnnd++; } bool flag=0; for(int i=mnnd;i<=16;i++) { mxnd=i; if(dfs(0,x,y,mnnd,-1)) { printf("%d\n",i-1); flag=1; break; } } if(!flag) printf("-1\n"); } return 0; }

P2324 [SCOI2005]騎士精神